Merge remote-tracking branch 'upstream/master' into fix14

This commit is contained in:
proller 2017-12-13 16:10:02 +03:00
commit 4076e14b6b
35 changed files with 501 additions and 187 deletions

View File

@ -33,7 +33,11 @@ START_HEADERS=$(echo \
# Опция -mcx16 для того, чтобы выбиралось больше заголовочных файлов (с запасом).
# The latter options are the same that are added while building packages.
GCC_ROOT=`$CLANG -v 2>&1 | grep "Selected GCC installation"| sed -n -e 's/^.*: //p'`
for src_file in $(echo | $CLANG -M -xc++ -std=c++1z -Wall -Werror -msse4 -mcx16 -mpopcnt -O3 -g -fPIC -fstack-protector -D_FORTIFY_SOURCE=2 \
-I $GCC_ROOT/include \
-I $GCC_ROOT/include-fixed \
$(cat "$BUILD_PATH/include_directories.txt") \
$(echo $START_HEADERS | sed -r -e 's/[^ ]+/-include \0/g') \
- |

View File

@ -1,6 +1,6 @@
# This strings autochanged from release_lib.sh:
set(VERSION_DESCRIBE v1.1.54325-testing)
set(VERSION_REVISION 54325)
set(VERSION_DESCRIBE v1.1.54326-testing)
set(VERSION_REVISION 54326)
# end of autochange
set (VERSION_MAJOR 1)

View File

@ -5,37 +5,39 @@
namespace DB
{
PushingToViewsBlockOutputStream::PushingToViewsBlockOutputStream(String database, String table, const Context & context_,
const ASTPtr & query_ptr_, bool no_destination)
PushingToViewsBlockOutputStream::PushingToViewsBlockOutputStream(
String database, String table, StoragePtr storage,
const Context & context_, const ASTPtr & query_ptr_, bool no_destination)
: context(context_), query_ptr(query_ptr_)
{
storage = context.getTable(database, table);
/** TODO This is a very important line. At any insertion into the table one of streams should own lock.
* Although now any insertion into the table is done via PushingToViewsBlockOutputStream,
* but it's clear that here is not the best place for this functionality.
*/
addTableLock(storage->lockStructure(true, __PRETTY_FUNCTION__));
Dependencies dependencies = context.getDependencies(database, table);
/// We need special context for materialized views insertions
if (!dependencies.empty())
if (!table.empty())
{
views_context = std::make_unique<Context>(context);
// Do not deduplicate insertions into MV if the main insertion is Ok
views_context->getSettingsRef().insert_deduplicate = false;
}
Dependencies dependencies = context.getDependencies(database, table);
for (const auto & database_table : dependencies)
{
auto dependent_table = context.getTable(database_table.first, database_table.second);
auto & materialized_view = dynamic_cast<const StorageMaterializedView &>(*dependent_table);
/// We need special context for materialized views insertions
if (!dependencies.empty())
{
views_context = std::make_unique<Context>(context);
// Do not deduplicate insertions into MV if the main insertion is Ok
views_context->getSettingsRef().insert_deduplicate = false;
}
auto query = materialized_view.getInnerQuery();
auto out = std::make_shared<PushingToViewsBlockOutputStream>(database_table.first, database_table.second, *views_context, ASTPtr());
for (const auto & database_table : dependencies)
{
auto dependent_table = context.getTable(database_table.first, database_table.second);
auto & materialized_view = dynamic_cast<const StorageMaterializedView &>(*dependent_table);
views.emplace_back(ViewInfo{std::move(query), database_table.first, database_table.second, std::move(out)});
auto query = materialized_view.getInnerQuery();
auto out = std::make_shared<PushingToViewsBlockOutputStream>(
database_table.first, database_table.second, dependent_table, *views_context, ASTPtr());
views.emplace_back(ViewInfo{std::move(query), database_table.first, database_table.second, std::move(out)});
}
}
/* Do not push to destination table if the flag is set */

View File

@ -19,7 +19,8 @@ class ReplicatedMergeTreeBlockOutputStream;
class PushingToViewsBlockOutputStream : public IBlockOutputStream
{
public:
PushingToViewsBlockOutputStream(String database, String table, const Context & context_, const ASTPtr & query_ptr_, bool no_destination = false);
PushingToViewsBlockOutputStream(String database, String table, StoragePtr storage,
const Context & context_, const ASTPtr & query_ptr_, bool no_destination = false);
void write(const Block & block) override;

View File

@ -141,10 +141,10 @@ struct SEHierarchyImpl
*/
struct RegionsHierarchyGetter
{
using Src = RegionsHierarchies;
using Dst = RegionsHierarchy;
using Src = const RegionsHierarchies;
using Dst = const RegionsHierarchy;
static const Dst & get(const Src & src, const std::string & key)
static Dst & get(Src & src, const std::string & key)
{
return src.get(key);
}
@ -155,10 +155,10 @@ struct RegionsHierarchyGetter
template <typename Dict>
struct IdentityDictionaryGetter
{
using Src = Dict;
using Dst = Dict;
using Src = const Dict;
using Dst = const Dict;
static const Dst & get(const Src & src, const std::string & key)
static Dst & get(Src & src, const std::string & key)
{
if (key.empty())
return src;
@ -670,10 +670,10 @@ public:
}
private:
const std::shared_ptr<RegionsNames> owned_dict;
const MultiVersion<RegionsNames>::Version owned_dict;
public:
FunctionRegionToName(const std::shared_ptr<RegionsNames> & owned_dict_)
FunctionRegionToName(const MultiVersion<RegionsNames>::Version & owned_dict_)
: owned_dict(owned_dict_)
{
if (!owned_dict)

View File

@ -8,17 +8,17 @@ endif ()
set (INTERNAL_COMPILER_EXECUTABLE "clickhouse-clang" CACHE STRING "")
set (INTERNAL_LINKER_EXECUTABLE "clickhouse-lld" CACHE STRING "")
set (INTERNAL_COMPILER_NO_WARNING OFF CACHE BOOL "")
set (INTERNAL_COMPILER_HEADERS "${PATH_SHARE}/clickhouse/headers" CACHE STRING "")
set (INTERNAL_COMPILER_HEADERS_ROOT "${INTERNAL_COMPILER_HEADERS}" CACHE STRING "")
set (INTERNAL_COMPILER_CUSTOM_ROOT ON CACHE BOOL "")
set (INTERNAL_COMPILER_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${CXX_FLAGS_INTERNAL_COMPILER} -x c++ -march=native -fPIC -fvisibility=hidden -fno-implement-inlines " CACHE STRING "")
set (INTERNAL_COMPILER_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${CXX_FLAGS_INTERNAL_COMPILER} -x c++ -march=native -fPIC -fvisibility=hidden -fno-implement-inlines -nostdinc -nostdinc++ -Bprefix=${PATH_SHARE}/clickhouse --isysroot=${INTERNAL_COMPILER_HEADERS_ROOT}" CACHE STRING "")
string(REPLACE "-no-pie" "" INTERNAL_COMPILER_FLAGS ${INTERNAL_COMPILER_FLAGS})
if (INTERNAL_COMPILER_NO_WARNING)
string (REPLACE "-Wall" "" INTERNAL_COMPILER_FLAGS ${INTERNAL_COMPILER_FLAGS})
string (REPLACE "-Werror" "" INTERNAL_COMPILER_FLAGS ${INTERNAL_COMPILER_FLAGS})
endif ()
set (INTERNAL_COMPILER_HEADERS "${PATH_SHARE}/clickhouse/headers" CACHE STRING "")
set (INTERNAL_COMPILER_HEADERS_ROOT "${INTERNAL_COMPILER_HEADERS}" CACHE STRING "")
set (INTERNAL_COMPILER_CUSTOM_ROOT ON CACHE BOOL "")
list(GET Poco_INCLUDE_DIRS 0 Poco_Foundation_INCLUDE_DIR)
list(GET Poco_INCLUDE_DIRS 1 Poco_Util_INCLUDE_DIR)

View File

@ -333,7 +333,7 @@ Cluster::Cluster(Poco::Util::AbstractConfiguration & config, const Settings & se
Cluster::Cluster(const Settings & settings, const std::vector<std::vector<String>> & names,
const String & username, const String & password, UInt16 clickhouse_port)
const String & username, const String & password, UInt16 clickhouse_port, bool treat_local_as_shared)
{
UInt32 current_shard_num = 1;
@ -348,23 +348,30 @@ Cluster::Cluster(const Settings & settings, const std::vector<std::vector<String
ConnectionPoolPtrs replicas;
replicas.reserve(current.size());
Addresses shard_local_addresses;
for (const auto & replica : current)
{
replicas.emplace_back(std::make_shared<ConnectionPool>(
settings.distributed_connections_pool_size,
replica.host_name, replica.port, replica.resolved_address,
replica.default_database, replica.user, replica.password,
"server", Protocol::Compression::Enable, Protocol::Encryption::Disable,
saturate(settings.connect_timeout_with_failover_ms, settings.limits.max_execution_time),
saturate(settings.receive_timeout, settings.limits.max_execution_time),
saturate(settings.send_timeout, settings.limits.max_execution_time)));
if (replica.is_local && !treat_local_as_shared)
shard_local_addresses.push_back(replica);
else
{
replicas.emplace_back(std::make_shared<ConnectionPool>(
settings.distributed_connections_pool_size,
replica.host_name, replica.port, replica.resolved_address,
replica.default_database, replica.user, replica.password,
"server", Protocol::Compression::Enable, Protocol::Encryption::Disable,
saturate(settings.connect_timeout_with_failover_ms, settings.limits.max_execution_time),
saturate(settings.receive_timeout, settings.limits.max_execution_time),
saturate(settings.send_timeout, settings.limits.max_execution_time)));
}
}
ConnectionPoolWithFailoverPtr shard_pool = std::make_shared<ConnectionPoolWithFailover>(
std::move(replicas), settings.load_balancing, settings.connections_with_failover_max_tries);
slot_to_shard.insert(std::end(slot_to_shard), default_weight, shards_info.size());
shards_info.push_back({{}, current_shard_num, default_weight, {}, shard_pool, false});
shards_info.push_back({{}, current_shard_num, default_weight, std::move(shard_local_addresses), shard_pool, false});
++current_shard_num;
}

View File

@ -18,11 +18,13 @@ class Cluster
public:
Cluster(Poco::Util::AbstractConfiguration & config, const Settings & settings, const String & cluster_name);
/// Construct a cluster by the names of shards and replicas. Local are treated as well as remote ones.
/// Construct a cluster by the names of shards and replicas.
/// Local are treated as well as remote ones if treat_local_as_shared is true.
/// 'clickhouse_port' - port that this server instance listen for queries.
/// This parameter is needed only to check that some address is local (points to ourself).
Cluster(const Settings & settings, const std::vector<std::vector<String>> & names,
const String & username, const String & password, UInt16 clickhouse_port);
const String & username, const String & password,
UInt16 clickhouse_port, bool treat_local_as_shared = true);
Cluster(const Cluster &) = delete;
Cluster & operator=(const Cluster &) = delete;

View File

@ -562,7 +562,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
std::make_shared<AddingDefaultBlockOutputStream>(
std::make_shared<MaterializingBlockOutputStream>(
std::make_shared<PushingToViewsBlockOutputStream>(
create.database, create.table,
create.database, create.table, res,
create.is_temporary ? context.getSessionContext() : context,
query_ptr)),
/// @note shouldn't these two contexts be session contexts in case of temporary table?

View File

@ -2,16 +2,19 @@
#include <Parsers/TablePropertiesQueriesASTs.h>
#include <DataStreams/OneBlockInputStream.h>
#include <DataStreams/BlockIO.h>
#include <DataStreams/copyData.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeString.h>
#include <Columns/ColumnString.h>
#include <Parsers/formatAST.h>
#include <Parsers/queryToString.h>
#include <Interpreters/Context.h>
#include <Interpreters/InterpreterDescribeQuery.h>
#include <Common/typeid_cast.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTFunction.h>
#include <TableFunctions/ITableFunction.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTTablesInSelectQuery.h>
namespace DB
@ -57,9 +60,47 @@ BlockInputStreamPtr InterpreterDescribeQuery::executeImpl()
NamesAndTypesList columns;
ColumnDefaults column_defaults;
StoragePtr table;
auto table_expression = typeid_cast<const ASTTableExpression *>(ast.table_expression.get());
if (table_expression->subquery)
columns = InterpreterSelectQuery::getSampleBlock(table_expression->subquery->children[0], context).getColumnsList();
else
{
StoragePtr table = context.getTable(ast.database, ast.table);
if (table_expression->table_function)
{
auto table_function = typeid_cast<const ASTFunction *>(table_expression->table_function.get());
/// Get the table function
TableFunctionPtr table_function_ptr = TableFunctionFactory::instance().get(table_function->name, context);
/// Run it and remember the result
table = table_function_ptr->execute(table_expression->table_function, context);
}
else
{
String database_name;
String table_name;
auto identifier = table_expression->database_and_table_name;
if (identifier->children.size() > 2)
throw Exception("Logical error: more than two components in table expression", ErrorCodes::LOGICAL_ERROR);
if (identifier->children.size() > 1)
{
auto database_ptr = identifier->children[0];
auto table_ptr = identifier->children[1];
if (database_ptr)
database_name = typeid_cast<ASTIdentifier &>(*database_ptr).name;
if (table_ptr)
table_name = typeid_cast<ASTIdentifier &>(*table_ptr).name;
}
else
table_name = typeid_cast<ASTIdentifier &>(*identifier).name;
table = context.getTable(database_name, table_name);
}
auto table_lock = table->lockStructure(false, __PRETTY_FUNCTION__);
columns = table->getColumnsList();
columns.insert(std::end(columns), std::begin(table->alias_columns), std::end(table->alias_columns));
@ -71,7 +112,7 @@ BlockInputStreamPtr InterpreterDescribeQuery::executeImpl()
ColumnWithTypeAndName default_type_column{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "default_type" };
ColumnWithTypeAndName default_expression_column{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "default_expression" };;
for (const auto column : columns)
for (const auto & column : columns)
{
name_column.column->insert(column.name);
type_column.column->insert(column.type->getName());

View File

@ -20,6 +20,8 @@
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <Parsers/ASTFunction.h>
namespace ProfileEvents
{
@ -42,14 +44,29 @@ InterpreterInsertQuery::InterpreterInsertQuery(const ASTPtr & query_ptr_, const
}
StoragePtr InterpreterInsertQuery::getTable()
StoragePtr InterpreterInsertQuery::loadTable()
{
ASTInsertQuery & query = typeid_cast<ASTInsertQuery &>(*query_ptr);
if (query.table_function)
{
auto table_function = typeid_cast<const ASTFunction *>(query.table_function.get());
const auto & factory = TableFunctionFactory::instance();
return factory.get(table_function->name, context)->execute(query.table_function, context);
}
/// In what table to write.
return context.getTable(query.database, query.table);
}
StoragePtr InterpreterInsertQuery::getTable()
{
if (!cached_table)
cached_table = loadTable();
return cached_table;
}
Block InterpreterInsertQuery::getSampleBlock()
{
ASTInsertQuery & query = typeid_cast<ASTInsertQuery &>(*query_ptr);
@ -93,7 +110,7 @@ BlockIO InterpreterInsertQuery::execute()
/// We create a pipeline of several streams, into which we will write data.
BlockOutputStreamPtr out;
out = std::make_shared<PushingToViewsBlockOutputStream>(query.database, query.table, context, query_ptr, query.no_destination);
out = std::make_shared<PushingToViewsBlockOutputStream>(query.database, query.table, table, context, query_ptr, query.no_destination);
out = std::make_shared<MaterializingBlockOutputStream>(out);

View File

@ -25,6 +25,10 @@ public:
BlockIO execute() override;
private:
/// Cache storage to avoid double table function call.
StoragePtr cached_table;
StoragePtr loadTable();
StoragePtr getTable();
Block getSampleBlock();

View File

@ -9,8 +9,15 @@ void ASTInsertQuery::formatImpl(const FormatSettings & settings, FormatState & s
{
frame.need_parens = false;
settings.ostr << (settings.hilite ? hilite_keyword : "") << "INSERT INTO " << (settings.hilite ? hilite_none : "")
<< (!database.empty() ? backQuoteIfNeed(database) + "." : "") << backQuoteIfNeed(table);
settings.ostr << (settings.hilite ? hilite_keyword : "") << "INSERT INTO ";
if (table_function)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << "FUNCTION ";
table_function->formatImpl(settings, state, frame);
}
else
settings.ostr << (settings.hilite ? hilite_none : "")
<< (!database.empty() ? backQuoteIfNeed(database) + "." : "") << backQuoteIfNeed(table);
if (columns)
{

View File

@ -17,6 +17,7 @@ public:
ASTPtr columns;
String format;
ASTPtr select;
ASTPtr table_function;
// Set to true if the data should only be inserted into attached views
bool no_destination = false;
@ -26,7 +27,7 @@ public:
const char * end = nullptr;
ASTInsertQuery() = default;
ASTInsertQuery(const StringRange range_) : IAST(range_) {}
explicit ASTInsertQuery(const StringRange range_) : IAST(range_) {}
/** Get the text that identifies this element. */
String getID() const override { return "InsertQuery_" + database + "_" + table; };
@ -38,6 +39,10 @@ public:
if (columns) { res->columns = columns->clone(); res->children.push_back(res->columns); }
if (select) { res->select = select->clone(); res->children.push_back(res->select); }
if (table_function)
{
res->table_function = table_function->clone(); res->children.push_back(res->table_function);
}
return res;
}

View File

@ -17,7 +17,7 @@ public:
ASTQueryWithOutput() = default;
explicit ASTQueryWithOutput(const StringRange range_) : IAST(range_) {}
void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const override final;
void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const final;
protected:
/// NOTE: call this helper at the end of the clone() method of descendant class.
@ -28,28 +28,28 @@ protected:
};
/// Declares the class-successor of ASTQueryWithOutput with implemented methods getID and clone.
#define DEFINE_AST_QUERY_WITH_OUTPUT(Name, ID, Query) \
class Name : public ASTQueryWithOutput \
{ \
public: \
Name() {} \
Name(StringRange range_) : ASTQueryWithOutput(range_) {} \
String getID() const override { return ID; }; \
\
ASTPtr clone() const override \
{ \
std::shared_ptr<Name> res = std::make_shared<Name>(*this); \
res->children.clear(); \
cloneOutputOptions(*res); \
return res; \
} \
\
protected: \
void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override \
{ \
settings.ostr << (settings.hilite ? hilite_keyword : "") << Query << (settings.hilite ? hilite_none : ""); \
} \
template <typename AstIDAndQueryNames>
class ASTQueryWithOutputImpl : public ASTQueryWithOutput
{
public:
explicit ASTQueryWithOutputImpl() = default;
explicit ASTQueryWithOutputImpl(StringRange range_) : ASTQueryWithOutput(range_) {}
String getID() const override { return AstIDAndQueryNames::ID; };
ASTPtr clone() const override
{
auto res = std::make_shared<ASTQueryWithOutputImpl<AstIDAndQueryNames>>(*this);
res->children.clear();
cloneOutputOptions(*res);
return res;
}
protected:
void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override
{
settings.ostr << (settings.hilite ? hilite_keyword : "")
<< AstIDAndQueryNames::Query << (settings.hilite ? hilite_none : "");
}
};
}

View File

@ -17,7 +17,7 @@ public:
String table;
ASTQueryWithTableAndOutput() = default;
ASTQueryWithTableAndOutput(const StringRange range_) : ASTQueryWithOutput(range_) {}
explicit ASTQueryWithTableAndOutput(const StringRange range_) : ASTQueryWithOutput(range_) {}
protected:
void formatHelper(const FormatSettings & settings, const char * name) const
@ -28,27 +28,29 @@ protected:
};
/// Declares the inheritance class of ASTQueryWithTableAndOutput with the implementation of methods getID and clone.
#define DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(Name, ID, Query) \
class Name : public ASTQueryWithTableAndOutput \
{ \
public: \
Name() = default; \
Name(const StringRange range_) : ASTQueryWithTableAndOutput(range_) {} \
String getID() const override { return ID"_" + database + "_" + table; }; \
\
ASTPtr clone() const override \
{ \
std::shared_ptr<Name> res = std::make_shared<Name>(*this); \
res->children.clear(); \
cloneOutputOptions(*res); \
return res; \
} \
\
protected: \
void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override \
{ \
formatHelper(settings, Query); \
} \
};
template <typename AstIDAndQueryNames>
class ASTQueryWithTableAndOutputImpl : public ASTQueryWithTableAndOutput
{
public:
ASTQueryWithTableAndOutputImpl() = default;
explicit ASTQueryWithTableAndOutputImpl(const StringRange range_) : ASTQueryWithTableAndOutput(range_) {}
String getID() const override { return AstIDAndQueryNames::ID + ("_" + database) + "_" + table; };
ASTPtr clone() const override
{
auto res = std::make_shared<ASTQueryWithTableAndOutputImpl<AstIDAndQueryNames>>(*this);
res->children.clear();
cloneOutputOptions(*res);
return res;
}
protected:
void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override
{
formatHelper(settings, AstIDAndQueryNames::Query);
}
};
}

View File

@ -6,6 +6,12 @@
namespace DB
{
DEFINE_AST_QUERY_WITH_OUTPUT(ASTShowProcesslistQuery, "ShowProcesslistQuery", "SHOW PROCESSLIST")
struct ASTShowProcesslisIDAndQueryNames
{
static constexpr auto ID = "ShowProcesslistQuery";
static constexpr auto Query = "SHOW PROCESSLIST";
};
using ASTShowProcesslistQuery = ASTQueryWithOutputImpl<ASTShowProcesslisIDAndQueryNames>;
}

View File

@ -0,0 +1,48 @@
#include <Parsers/ASTIdentifier.h>
#include <Parsers/TablePropertiesQueriesASTs.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ParserDescribeTableQuery.h>
#include <Parsers/ParserTablesInSelectQuery.h>
#include <Common/typeid_cast.h>
namespace DB
{
bool ParserDescribeTableQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
Pos begin = pos;
ParserKeyword s_describe("DESCRIBE");
ParserKeyword s_desc("DESC");
ParserKeyword s_table("TABLE");
ParserToken s_dot(TokenType::Dot);
ParserIdentifier name_p;
ASTPtr database;
ASTPtr table;
if (!s_describe.ignore(pos, expected) && !s_desc.ignore(pos, expected))
return false;
auto query = std::make_shared<ASTDescribeQuery>();
s_table.ignore(pos, expected);
ASTPtr table_expression;
if (!ParserTableExpression().parse(pos, table_expression, expected))
return false;
query->range = StringRange(begin, pos);
query->table_expression = table_expression;
node = query;
return true;
}
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <Parsers/IParserBase.h>
#include <Parsers/ParserQueryWithOutput.h>
#include <Parsers/ExpressionElementParsers.h>
namespace DB
{
/** Query (DESCRIBE | DESC) ([TABLE] [db.]name | tableFunction) [FORMAT format]
*/
class ParserDescribeTableQuery : public IParserBase
{
protected:
const char * getName() const { return "DESCRIBE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
};
}

View File

@ -8,6 +8,7 @@
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/ParserSelectQuery.h>
#include <Parsers/ParserInsertQuery.h>
#include <Parsers/ASTFunction.h>
#include <Common/typeid_cast.h>
@ -26,6 +27,8 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
Pos begin = pos;
ParserKeyword s_insert_into("INSERT INTO");
ParserKeyword s_table("TABLE");
ParserKeyword s_function("FUNCTION");
ParserToken s_dot(TokenType::Dot);
ParserKeyword s_values("VALUES");
ParserKeyword s_format("FORMAT");
@ -34,26 +37,39 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
ParserToken s_rparen(TokenType::ClosingRoundBracket);
ParserIdentifier name_p;
ParserList columns_p(std::make_unique<ParserCompoundIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma), false);
ParserFunction table_function_p;
ASTPtr database;
ASTPtr table;
ASTPtr columns;
ASTPtr format;
ASTPtr select;
ASTPtr table_function;
/// Insertion data
const char * data = nullptr;
if (!s_insert_into.ignore(pos, expected))
return false;
if (!name_p.parse(pos, table, expected))
return false;
s_table.ignore(pos, expected);
if (s_dot.ignore(pos, expected))
if (s_function.ignore(pos, expected))
{
if (!table_function_p.parse(pos, table_function, expected))
return false;
static_cast<ASTFunction &>(*table_function).kind = ASTFunction::TABLE_FUNCTION;
}
else
{
database = table;
if (!name_p.parse(pos, table, expected))
return false;
if (s_dot.ignore(pos, expected))
{
database = table;
if (!name_p.parse(pos, table, expected))
return false;
}
}
/// Is there a list of columns
@ -117,10 +133,17 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
auto query = std::make_shared<ASTInsertQuery>(StringRange(begin, pos));
node = query;
if (database)
query->database = typeid_cast<ASTIdentifier &>(*database).name;
if (table_function)
{
query->table_function = table_function;
}
else
{
if (database)
query->database = typeid_cast<ASTIdentifier &>(*database).name;
query->table = typeid_cast<ASTIdentifier &>(*table).name;
query->table = typeid_cast<ASTIdentifier &>(*table).name;
}
if (format)
query->format = typeid_cast<ASTIdentifier &>(*format).name;

View File

@ -2,6 +2,7 @@
#include <Parsers/ParserShowTablesQuery.h>
#include <Parsers/ParserSelectQuery.h>
#include <Parsers/ParserTablePropertiesQuery.h>
#include <Parsers/ParserDescribeTableQuery.h>
#include <Parsers/ParserShowProcesslistQuery.h>
#include <Parsers/ParserCheckQuery.h>
#include <Parsers/ParserCreateQuery.h>
@ -19,6 +20,7 @@ bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
ParserShowTablesQuery show_tables_p;
ParserSelectQuery select_p;
ParserTablePropertiesQuery table_p;
ParserDescribeTableQuery describe_table_p;
ParserShowProcesslistQuery show_processlist_p;
ParserCreateQuery create_p;
ParserAlterQuery alter_p;
@ -32,6 +34,7 @@ bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
bool parsed = select_p.parse(pos, query, expected)
|| show_tables_p.parse(pos, query, expected)
|| table_p.parse(pos, query, expected)
|| describe_table_p.parse(pos, query, expected)
|| show_processlist_p.parse(pos, query, expected)
|| create_p.parse(pos, query, expected)
|| alter_p.parse(pos, query, expected)

View File

@ -32,10 +32,6 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
{
query = std::make_shared<ASTExistsQuery>();
}
else if (s_describe.ignore(pos, expected) || s_desc.ignore(pos, expected))
{
query = std::make_shared<ASTDescribeQuery>();
}
else if (s_show.ignore(pos, expected))
{
if (!s_create.ignore(pos, expected))

View File

@ -8,13 +8,13 @@
namespace DB
{
/** Query (EXISTS | SHOW CREATE | (DESCRIBE | DESC)) [TABLE] [db.]name [FORMAT format]
/** Query (EXISTS | SHOW CREATE) [TABLE] [db.]name [FORMAT format]
*/
class ParserTablePropertiesQuery : public IParserBase
{
protected:
const char * getName() const { return "EXISTS, SHOW CREATE or DESCRIBE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "EXISTS or SHOW CREATE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -6,8 +6,57 @@
namespace DB
{
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTExistsQuery, "ExistsQuery", "EXISTS TABLE")
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTShowCreateQuery, "ShowCreateQuery", "SHOW CREATE TABLE")
DEFINE_AST_QUERY_WITH_TABLE_AND_OUTPUT(ASTDescribeQuery, "DescribeQuery", "DESCRIBE TABLE")
struct ASTExistsQueryIDAndQueryNames
{
static constexpr auto ID = "ExistsQuery";
static constexpr auto Query = "EXISTS TABLE";
};
struct ASTShowCreateQueryIDAndQueryNames
{
static constexpr auto ID = "ShowCreateQuery";
static constexpr auto Query = "SHOW CREATE TABLE";
};
struct ASTDescribeQueryExistsQueryIDAndQueryNames
{
static constexpr auto ID = "DescribeQuery";
static constexpr auto Query = "DESCRIBE TABLE";
};
using ASTExistsQuery = ASTQueryWithTableAndOutputImpl<ASTExistsQueryIDAndQueryNames>;
using ASTShowCreateQuery = ASTQueryWithTableAndOutputImpl<ASTShowCreateQueryIDAndQueryNames>;
class ASTDescribeQuery : public ASTQueryWithOutput
{
public:
ASTPtr table_expression;
ASTDescribeQuery() = default;
explicit ASTDescribeQuery(StringRange range_) : ASTQueryWithOutput(range_) {}
String getID() const override { return "DescribeQuery"; };
ASTPtr clone() const override
{
auto res = std::make_shared<ASTDescribeQuery>(*this);
res->children.clear();
if (table_expression)
{
res->table_expression = table_expression->clone();
res->children.push_back(res->table_expression);
}
cloneOutputOptions(*res);
return res;
}
protected:
void formatQueryImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
settings.ostr << (settings.hilite ? hilite_keyword : "")
<< "DESCRIBE TABLE " << (settings.hilite ? hilite_none : "");
table_expression->formatImpl(settings, state, frame);
}
};
}

View File

@ -72,8 +72,11 @@ if (CLICKHOUSE_SPLIT_BINARY)
target_link_libraries (clickhouse-clang clickhouse-compiler-lib)
add_executable (clickhouse-lld clickhouse-lld.cpp)
target_link_libraries (clickhouse-lld clickhouse-compiler-lib)
install (TARGETS clickhouse-clang clickhouse-lld RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT clickhouse)
endif ()
install (TARGETS clickhouse-server clickhouse-client clickhouse-local clickhouse-benchmark clickhouse-performance-test clickhouse-format RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT clickhouse)
add_custom_target (clickhouse ALL DEPENDS clickhouse-server clickhouse-client clickhouse-local clickhouse-benchmark clickhouse-performance-test clickhouse-extract-from-config clickhouse-compressor clickhouse-format)
else ()
add_executable (clickhouse main.cpp)
@ -94,7 +97,6 @@ else ()
target_link_libraries (clickhouse clickhouse-compiler-lib)
endif ()
install (TARGETS clickhouse RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT clickhouse)
add_custom_target (clickhouse-server ALL COMMAND ${CMAKE_COMMAND} -E create_symlink clickhouse clickhouse-server DEPENDS clickhouse)
add_custom_target (clickhouse-client ALL COMMAND ${CMAKE_COMMAND} -E create_symlink clickhouse clickhouse-client DEPENDS clickhouse)
@ -105,6 +107,18 @@ else ()
# install always because depian package want this files:
add_custom_target (clickhouse-clang ALL COMMAND ${CMAKE_COMMAND} -E create_symlink clickhouse clickhouse-clang DEPENDS clickhouse)
add_custom_target (clickhouse-lld ALL COMMAND ${CMAKE_COMMAND} -E create_symlink clickhouse clickhouse-lld DEPENDS clickhouse)
install (TARGETS clickhouse RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT clickhouse)
install (FILES
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-server
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-client
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-local
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-benchmark
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-performance-test
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-format
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-clang
${CMAKE_CURRENT_BINARY_DIR}/clickhouse-lld
DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT clickhouse)
endif ()
install (

View File

@ -39,6 +39,7 @@
#include <memory>
#include <boost/filesystem.hpp>
#include <Parsers/ASTTablesInSelectQuery.h>
namespace DB
@ -71,6 +72,7 @@ ASTPtr rewriteInsertQuery(const ASTPtr & query, const std::string & database, co
auto & actual_query = typeid_cast<ASTInsertQuery &>(*modified_query_ast);
actual_query.database = database;
actual_query.table = table;
actual_query.table_function = nullptr;
/// make sure query is not INSERT SELECT
actual_query.select = nullptr;
@ -219,10 +221,12 @@ BlockInputStreams StorageDistributed::read(
BlockOutputStreamPtr StorageDistributed::write(const ASTPtr & query, const Settings & settings)
{
auto cluster = context.getCluster(cluster_name);
auto cluster = owned_cluster ? owned_cluster : context.getCluster(cluster_name);
/// TODO: !path.empty() can be replaced by !owned_cluster or !cluster_name.empty() ?
bool write_enabled = !path.empty() && (((cluster->getLocalShardCount() + cluster->getRemoteShardCount()) < 2) || has_sharding_key);
/// owned_cluster for remote table function use sync insertion => doesn't need a path.
bool write_enabled = (!path.empty() || owned_cluster)
&& (((cluster->getLocalShardCount() + cluster->getRemoteShardCount()) < 2) || has_sharding_key);
if (!write_enabled)
throw Exception{
@ -230,9 +234,12 @@ BlockOutputStreamPtr StorageDistributed::write(const ASTPtr & query, const Setti
" with more than one shard and no sharding key provided",
ErrorCodes::STORAGE_REQUIRES_PARAMETER};
bool insert_sync = settings.insert_distributed_sync || owned_cluster;
auto timeout = settings.insert_distributed_timeout;
/// DistributedBlockOutputStream will not own cluster, but will own ConnectionPools of the cluster
return std::make_shared<DistributedBlockOutputStream>(
*this, rewriteInsertQuery(query, remote_database, remote_table), cluster, settings.insert_distributed_sync, settings.insert_distributed_timeout);
*this, rewriteInsertQuery(query, remote_database, remote_table), cluster, insert_sync, timeout);
}
@ -269,16 +276,30 @@ BlockInputStreams StorageDistributed::describe(const Context & context, const Se
/// Create DESCRIBE TABLE query.
auto cluster = getCluster();
ASTPtr describe_query_ptr = std::make_shared<ASTDescribeQuery>();
auto & describe_query = static_cast<ASTDescribeQuery &>(*describe_query_ptr);
auto describe_query = std::make_shared<ASTDescribeQuery>();
describe_query.database = remote_database;
describe_query.table = remote_table;
std::string name = remote_database + '.' + remote_table;
auto id = std::make_shared<ASTIdentifier>();
id->name = name;
auto desc_database = std::make_shared<ASTIdentifier>();
auto desc_table = std::make_shared<ASTIdentifier>();
desc_database->name = remote_database;
desc_table->name = remote_table;
id->children.push_back(desc_database);
id->children.push_back(desc_table);
auto table_expression = std::make_shared<ASTTableExpression>();
table_expression->database_and_table_name = id;
describe_query->table_expression = table_expression;
ClusterProxy::DescribeStreamFactory describe_stream_factory;
return ClusterProxy::executeQuery(
describe_stream_factory, cluster, describe_query_ptr, context, settings);
describe_stream_factory, cluster, describe_query, context, settings);
}

View File

@ -284,8 +284,8 @@ void TinyLogBlockOutputStream::writeSuffix()
done = true;
/// Finish write.
for (FileStreams::iterator it = streams.begin(); it != streams.end(); ++it)
it->second->finalize();
for (auto & stream : streams)
stream.second->finalize();
std::vector<Poco::File> column_files;
for (auto & pair : streams)

View File

@ -0,0 +1,30 @@
date Date
val UInt64
val2 UInt8 DEFAULT 42
val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8)
val4 UInt64 ALIAS val
-
date Date
val UInt64
val2 UInt8 DEFAULT 42
val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8)
val4 UInt64 ALIAS val
-
date Date
val UInt64
val2 UInt8
val3 UInt8
val4 UInt64
-
date Date
val UInt64
val2 UInt8
val3 UInt8
val4 UInt64
-
1 UInt8
-
1 UInt8
-
number UInt64
-

View File

@ -0,0 +1,17 @@
drop table if exists test.tab;
create table test.tab (date Date, val UInt64, val2 UInt8 default 42, val3 UInt8 default val2 + 1, val4 UInt64 alias val) engine = MergeTree(date, (date, val), 8192);
desc test.tab;
select '-';
desc table test.tab;
select '-';
desc remote('localhost', test.tab);
select '-';
desc table remote('localhost', test.tab);
select '-';
desc (select 1);
select '-';
desc table (select 1);
select '-';
desc (select * from system.numbers);
select '-';

4
debian/changelog vendored
View File

@ -1,5 +1,5 @@
clickhouse (1.1.54325) unstable; urgency=low
clickhouse (1.1.54326) unstable; urgency=low
* Modified source code
-- <robot-metrika-test@yandex-team.ru> Thu, 07 Dec 2017 16:08:12 +0300
-- <robot-metrika-test@yandex-team.ru> Wed, 13 Dec 2017 12:55:19 +0300

View File

@ -102,12 +102,12 @@ Formatting
.. code-block:: cpp
template <typename T, typename Ptr = std::shared_ptr<T>>
template <typename T>
class MultiVersion
{
public:
/// Конкретная версия объекта для использования. shared_ptr определяет время жизни версии.
using Version = Ptr;
/// Version of object for usage. shared_ptr manage lifetime of version.
using Version = std::shared_ptr<const T>;
#. If there's only one namespace in a file and there's nothing else significant - no need to indent the namespace.
@ -116,12 +116,9 @@ Formatting
.. code-block:: cpp
/// Если файлы не открыты, то открываем их.
if (streams.empty())
for (const auto & name : column_names)
streams.emplace(name, std::make_unique<Stream>(
storage.files[name].data_file.path(),
storage.files[name].marks[mark_number].offset));
/// Finish write.
for (auto & stream : streams)
stream.second->finalize();
#. No spaces before end of line.
@ -511,7 +508,7 @@ How to write code
#. Numeric types.
Use types UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, as well as size_t, ssize_t, ptrdiff_t.
Do not use типы signed/unsigned long, long long, short; signed char, unsigned char, аnd char.
Do not use signed/unsigned long, long long, short; signed char, unsigned char, аnd char.
#. Passing arguments.
Pass complex values by reference (including std::string).

View File

@ -22,6 +22,6 @@ Load data:
.. code-block:: bash
for i in {2007..2016}; do for j in {01..12}; do echo $i-$j >&2; curl -sS "http://dumps.wikimedia.org/other/pagecounts-raw/$i/$i-$j/" | grep -oE 'pagecounts-[0-9]+-[0-9]+\.gz'; done; done | sort | uniq | tee links.txt
for i in {2007..2016}; do for j in {01..12}; do echo $i-$j >&2; curl -sSL "http://dumps.wikimedia.org/other/pagecounts-raw/$i/$i-$j/" | grep -oE 'pagecounts-[0-9]+-[0-9]+\.gz'; done; done | sort | uniq | tee links.txt
cat links.txt | while read link; do wget http://dumps.wikimedia.org/other/pagecounts-raw/$(echo $link | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})[0-9]{2}-[0-9]+\.gz/\1/')/$(echo $link | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})[0-9]{2}-[0-9]+\.gz/\1-\2/')/$link; done
ls -1 /opt/wikistat/ | grep gz | while read i; do echo $i; gzip -cd /opt/wikistat/$i | ./wikistat-loader --time="$(echo -n $i | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]{2})([0-9]{2})([0-9]{2})\.gz/\1-\2-\3 \4-00-00/')" | clickhouse-client --query="INSERT INTO wikistat FORMAT TabSeparated"; done

View File

@ -79,12 +79,12 @@
14. В классах и структурах, public, private, protected пишется на том же уровне, что и class/struct, а все остальные внутренности - глубже.
```cpp
template <typename T, typename Ptr = std::shared_ptr<T>>
template <typename T>
class MultiVersion
{
public:
/// Конкретная версия объекта для использования. shared_ptr определяет время жизни версии.
using Version = Ptr;
/// Version of object for usage. shared_ptr manage lifetime of version.
using Version = std::shared_ptr<const T>;
...
}
```
@ -92,12 +92,9 @@
16. Если блок для выражения if, for, while... состоит из одного statement-а, то фигурные скобки писать не обязательно. Вместо этого поместите statement на отдельную строку. Этим statement-ом также может быть вложенный if, for, while... Но если внутренний statement содержит фигурные скобки или else, то у внешнего блок следует писать в фигурных скобках.
```cpp
/// Если файлы не открыты, то открываем их.
if (streams.empty())
for (const auto & name : column_names)
streams.emplace(name, std::make_unique<Stream>(
storage.files[name].data_file.path(),
storage.files[name].marks[mark_number].offset));
/// Finish write.
for (auto & stream : streams)
stream.second->finalize();
```
17. Не должно быть пробелов на концах строк.

View File

@ -20,7 +20,7 @@ CREATE TABLE wikistat
Загрузка данных:
```bash
for i in {2007..2016}; do for j in {01..12}; do echo $i-$j >&2; curl -sS "http://dumps.wikimedia.org/other/pagecounts-raw/$i/$i-$j/" | grep -oE 'pagecounts-[0-9]+-[0-9]+\.gz'; done; done | sort | uniq | tee links.txt
for i in {2007..2016}; do for j in {01..12}; do echo $i-$j >&2; curl -sSL "http://dumps.wikimedia.org/other/pagecounts-raw/$i/$i-$j/" | grep -oE 'pagecounts-[0-9]+-[0-9]+\.gz'; done; done | sort | uniq | tee links.txt
cat links.txt | while read link; do wget http://dumps.wikimedia.org/other/pagecounts-raw/$(echo $link | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})[0-9]{2}-[0-9]+\.gz/\1/')/$(echo $link | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})[0-9]{2}-[0-9]+\.gz/\1-\2/')/$link; done
ls -1 /opt/wikistat/ | grep gz | while read i; do echo $i; gzip -cd /opt/wikistat/$i | ./wikistat-loader --time="$(echo -n $i | sed -r 's/pagecounts-([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]{2})([0-9]{2})([0-9]{2})\.gz/\1-\2-\3 \4-00-00/')" | clickhouse-client --query="INSERT INTO wikistat FORMAT TabSeparated"; done
```

View File

@ -4,40 +4,40 @@
#include <memory>
/** Позволяет хранить некоторый объект, использовать его read-only в разных потоках,
* и заменять его на другой в других потоках.
* Замена производится атомарно, при этом, читающие потоки могут работать с разными версиями объекта.
/** Allow to store and read-only usage of an object in several threads,
* and to atomically replace an object in another thread.
* The replacement is atomic and reading threads can work with different versions of an object.
*
* Использование:
* MultiVersion<T> x;
* - при обновлении данных:
* x.set(new value);
* - при использовании данных для чтения в разных потоках:
* {
* MultiVersion<T>::Version current_version = x.get();
* // используем для чего-нибудь *current_version
* } // здесь перестаём владеть версией; если версия устарела, и её никто больше не использует - она будет уничтожена
* Usage:
* MultiVersion<T> x;
* - on data update:
* x.set(new value);
* - on read-only usage:
* {
* MultiVersion<T>::Version current_version = x.get();
* // use *current_version
* } // now we finish own current version; if the version is outdated and no one else is using it - it will be destroyed.
*
* Все методы thread-safe.
* All methods are thread-safe.
*/
template <typename T, typename Ptr = std::shared_ptr<T>>
template <typename T>
class MultiVersion
{
public:
/// Конкретная версия объекта для использования. shared_ptr определяет время жизни версии.
using Version = Ptr;
/// Version of object for usage. shared_ptr manage lifetime of version.
using Version = std::shared_ptr<const T>;
/// Инициализация по-умолчанию (NULL-ом).
/// Default initialization - by nullptr.
MultiVersion() = default;
/// Инициализация первой версией.
/// Initialization with first version.
MultiVersion(const Version & value)
{
set(value);
}
/// Захватить владение первой версией.
MultiVersion(T * value)
/// Take an ownership of first version.
MultiVersion(const T * value)
{
set(value);
}
@ -47,33 +47,33 @@ public:
set(std::move(value));
}
MultiVersion(std::unique_ptr<T> && value)
MultiVersion(std::unique_ptr<const T> && value)
{
set(std::move(value));
}
/// Получить текущую версию для использования. Возвращает shared_ptr, который определяет время жизни версии.
/// Obtain current version for read-only usage. Returns shared_ptr, that manages lifetime of version.
const Version get() const
{
/// TODO: можно ли заменять shared_ptr lock-free? (Можно, если сделать свою реализацию с использованием cmpxchg16b.)
std::lock_guard<std::mutex> lock(mutex);
/// NOTE: is it possible to lock-free replace of shared_ptr?
std::lock_guard lock(mutex);
return current_version;
}
/// Обновить объект новой версией.
void set(Version value)
/// Update an object with new version.
void set(const Version & value)
{
std::lock_guard<std::mutex> lock(mutex);
std::lock_guard lock(mutex);
current_version = value;
}
/// Обновить объект новой версией и захватить владение.
void set(T * value)
/// Update an object with new version and take an ownership of it.
void set(const T * value)
{
set(Version(value));
}
void set(std::unique_ptr<T> && value)
void set(std::unique_ptr<const T> && value)
{
set(Version(value.release()));
}