mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge remote-tracking branch 'upstream/master' into fix14
This commit is contained in:
commit
4076e14b6b
@ -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') \
|
||||
- |
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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?
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 : "");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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>;
|
||||
|
||||
}
|
||||
|
48
dbms/src/Parsers/ParserDescribeTableQuery.cpp
Normal file
48
dbms/src/Parsers/ParserDescribeTableQuery.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
21
dbms/src/Parsers/ParserDescribeTableQuery.h
Normal file
21
dbms/src/Parsers/ParserDescribeTableQuery.h
Normal 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);
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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 (
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
-
|
@ -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
4
debian/changelog
vendored
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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. Не должно быть пробелов на концах строк.
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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()));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user