This commit is contained in:
Mikhail Korotov 2020-01-22 15:49:41 +03:00
commit afa9299602
59 changed files with 685 additions and 259 deletions

View File

@ -7,16 +7,20 @@ Changelog category (leave one):
- Performance Improvement
- Backward Incompatible Change
- Build/Testing/Packaging Improvement
- Documentation
- Documentation (changelog entry is not required)
- Other
- Non-significant (changelog entry is not needed)
- Non-significant (changelog entry is not required)
Changelog entry (up to few sentences, required except for Non-significant/Documentation categories):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
...
Detailed description (optional):
Detailed description / Documentation draft:
...
By adding documentation, you'll allow users to try your new feature immediately, not when someone else will have time to document it later. Documentation is necessary for all features that affect user experience in any way. You can add brief documentation draft above, or add documentation right into your patch as Markdown files in [docs](https://github.com/ClickHouse/ClickHouse/tree/master/docs) folder.
If you are doing this for the first time, it's recommended to read the lightweight [Contributing to ClickHouse Documentation](https://github.com/ClickHouse/ClickHouse/tree/master/docs/README.md) guide first.

View File

@ -1,10 +1,16 @@
# Contributing to ClickHouse
## Technical info
Developer guide for writing code for ClickHouse is published on official website alongside the usage and operations documentation:
https://clickhouse.yandex/docs/en/development/architecture/
ClickHouse is an open project, and you can contribute to it in many ways. You can help with ideas, code, or documentation. We appreciate any efforts that help us to make the project better.
## Legal info
Thank you.
## Technical Info
We have a [developer's guide](https://clickhouse.yandex/docs/en/development/developer_instruction/) for writing code for ClickHouse. Besides this guide, you can find [Overview of ClickHouse Architecture](https://clickhouse.yandex/docs/en/development/architecture/) and instructions on how to build ClickHouse in different environments.
If you want to contribute to documentation, read the [Contributing to ClickHouse Documentation](docs/README.md) guide.
## Legal Info
In order for us (YANDEX LLC) to accept patches and other contributions from you, you will have to adopt our Yandex Contributor License Agreement (the "**CLA**"). The current version of the CLA you may find here:
1) https://yandex.ru/legal/cla/?lang=en (in English) and

View File

@ -177,7 +177,7 @@ elseif (COMPILER_GCC)
# Warn for suspicious length parameters to certain string and memory built-in functions if the argument uses sizeof
add_cxx_compile_options(-Wsizeof-pointer-memaccess)
# Warn about overriding virtual functions that are not marked with the override keyword
# add_cxx_compile_options(-Wsuggest-override)
add_cxx_compile_options(-Wsuggest-override)
# Warn whenever a switch statement has an index of boolean type and the case values are outside the range of a boolean type
add_cxx_compile_options(-Wswitch-bool)
# Warn if a self-comparison always evaluates to true or false

View File

@ -101,7 +101,7 @@ public:
}
void initialize(Poco::Util::Application & self [[maybe_unused]])
void initialize(Poco::Util::Application & self [[maybe_unused]]) override
{
std::string home_path;
const char * home_path_cstr = getenv("HOME");
@ -111,7 +111,7 @@ public:
configReadClient(config(), home_path);
}
int main(const std::vector<std::string> &)
int main(const std::vector<std::string> &) override
{
if (!json_path.empty() && Poco::File(json_path).exists()) /// Clear file with previous results
Poco::File(json_path).remove();
@ -492,7 +492,7 @@ private:
public:
~Benchmark()
~Benchmark() override
{
shutdown = true;
}

View File

@ -205,7 +205,7 @@ private:
ConnectionParameters connection_parameters;
void initialize(Poco::Util::Application & self)
void initialize(Poco::Util::Application & self) override
{
Poco::Util::Application::initialize(self);
@ -233,7 +233,7 @@ private:
}
int main(const std::vector<std::string> & /*args*/)
int main(const std::vector<std::string> & /*args*/) override
{
try
{

View File

@ -111,7 +111,7 @@ public:
server_display_name = server.config().getString("display_name", getFQDNOrHostName());
}
void run();
void run() override;
/// This method is called right before the query execution.
virtual void customizeContext(DB::Context & /*context*/) {}

View File

@ -34,6 +34,7 @@
<!--display_name>production</display_name--> <!-- It is the name that will be shown in the client -->
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<mysql_port>9004</mysql_port>
<!-- For HTTPS and SSL over native protocol. -->
<!--
<https_port>8443</https_port>

View File

@ -49,7 +49,7 @@
In first line will be password and in second - corresponding SHA256.
How to generate double SHA1:
Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | openssl dgst -sha1 -binary | openssl dgst -sha1
Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
In first line will be password and in second - corresponding double SHA1.
-->
<password></password>

View File

@ -99,7 +99,7 @@ class ExternalTablesHandler : public Poco::Net::PartHandler, BaseExternalTable
public:
ExternalTablesHandler(Context & context_, const Poco::Net::NameValueCollection & params_) : context(context_), params(params_) {}
void handlePart(const Poco::Net::MessageHeader & header, std::istream & stream);
void handlePart(const Poco::Net::MessageHeader & header, std::istream & stream) override;
private:
Context & context;

View File

@ -66,6 +66,8 @@ struct BlockIO
finish_callback = rhs.finish_callback;
exception_callback = rhs.exception_callback;
null_format = rhs.null_format;
return *this;
}
};

View File

@ -5,7 +5,6 @@
#include <Common/quoteString.h>
#include <Parsers/IAST.h>
namespace DB
{
@ -65,8 +64,18 @@ ConvertingBlockInputStream::ConvertingBlockInputStream(
throw Exception("Cannot find column " + backQuote(res_elem.name) + " in source stream",
ErrorCodes::THERE_IS_NO_COLUMN);
break;
case MatchColumnsMode::NameOrDefault:
if (input_header.has(res_elem.name))
conversion[result_col_num] = input_header.getPositionByName(res_elem.name);
else
conversion[result_col_num] = USE_DEFAULT;
break;
}
if (conversion[result_col_num] == USE_DEFAULT)
continue;
const auto & src_elem = input_header.getByPosition(conversion[result_col_num]);
/// Check constants.
@ -100,9 +109,18 @@ Block ConvertingBlockInputStream::readImpl()
Block res = header.cloneEmpty();
for (size_t res_pos = 0, size = conversion.size(); res_pos < size; ++res_pos)
{
const auto & src_elem = src.getByPosition(conversion[res_pos]);
auto & res_elem = res.getByPosition(res_pos);
if (conversion[res_pos] == USE_DEFAULT)
{
// Create a column with default values
auto column_with_defaults = res_elem.type->createColumn()->cloneResized(src.rows());
res_elem.column = std::move(column_with_defaults);
continue;
}
const auto & src_elem = src.getByPosition(conversion[res_pos]);
ColumnPtr converted = castColumnWithDiagnostic(src_elem, res_elem, context);
if (isColumnConst(*src_elem.column) && !isColumnConst(*res_elem.column))
@ -114,3 +132,4 @@ Block ConvertingBlockInputStream::readImpl()
}
}

View File

@ -28,7 +28,9 @@ public:
/// Require same number of columns in source and result. Match columns by corresponding positions, regardless to names.
Position,
/// Find columns in source by their names. Allow excessive columns in source.
Name
Name,
/// Find columns in source by their names if present else use the default. Allow excessive columns in source.
NameOrDefault
};
ConvertingBlockInputStream(
@ -48,6 +50,7 @@ private:
/// How to construct result block. Position in source block, where to get each column.
using Conversion = std::vector<size_t>;
const size_t USE_DEFAULT = static_cast<size_t>(-1);
Conversion conversion;
};

View File

@ -230,7 +230,7 @@ void PushingToViewsBlockOutputStream::process(const Block & block, size_t view_n
/// and two-level aggregation is triggered).
in = std::make_shared<SquashingBlockInputStream>(
in, context.getSettingsRef().min_insert_block_size_rows, context.getSettingsRef().min_insert_block_size_bytes);
in = std::make_shared<ConvertingBlockInputStream>(context, in, view.out->getHeader(), ConvertingBlockInputStream::MatchColumnsMode::Name);
in = std::make_shared<ConvertingBlockInputStream>(context, in, view.out->getHeader(), ConvertingBlockInputStream::MatchColumnsMode::NameOrDefault);
}
else
in = std::make_shared<OneBlockInputStream>(block);

View File

@ -60,7 +60,7 @@ std::ostream & operator<<(std::ostream & ostr, const TypesTestCase & test_case)
class TypeTest : public ::testing::TestWithParam<TypesTestCase>
{
public:
void SetUp()
void SetUp() override
{
const auto & p = GetParam();
from_types = typesFromString(p.from_types);

View File

@ -9,6 +9,7 @@ namespace DB
DatabaseMemory::DatabaseMemory(const String & name_)
: DatabaseWithOwnTablesBase(name_, "DatabaseMemory(" + name_ + ")")
, data_path("data/" + escapeForFileName(database_name) + "/")
{}
void DatabaseMemory::createTable(

View File

@ -1,6 +1,8 @@
#pragma once
#include <Databases/DatabasesCommon.h>
#include <Common/escapeForFileName.h>
#include <Parsers/ASTCreateQuery.h>
namespace Poco { class Logger; }
@ -32,6 +34,16 @@ public:
const String & table_name) override;
ASTPtr getCreateDatabaseQuery(const Context & /*context*/) const override;
/// DatabaseMemory allows to create tables, which store data on disk.
/// It's needed to create such tables in default database of clickhouse-local.
/// TODO May be it's better to use DiskMemory for such tables.
/// To save data on disk it's possible to explicitly CREATE DATABASE db ENGINE=Ordinary in clickhouse-local.
String getTableDataPath(const String & table_name) const override { return data_path + escapeForFileName(table_name) + "/"; }
String getTableDataPath(const ASTCreateQuery & query) const override { return getTableDataPath(query.table); }
private:
String data_path;
};
}

View File

@ -56,13 +56,13 @@ public:
DatabaseTablesSnapshotIterator(Tables && tables_) : tables(tables_), it(tables.begin()) {}
void next() { ++it; }
void next() override { ++it; }
bool isValid() const { return it != tables.end(); }
bool isValid() const override { return it != tables.end(); }
const String & name() const { return it->first; }
const String & name() const override { return it->first; }
const StoragePtr & table() const { return it->second; }
const StoragePtr & table() const override { return it->second; }
};
/// Copies list of dictionaries and iterates through such snapshot.

View File

@ -5,6 +5,10 @@
#include <IO/ReadHelpers.h>
#include <IO/WriteHelpers.h>
#if !__clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
template <typename T>
DB::DiskPtr createDisk();

View File

@ -121,6 +121,11 @@ struct NumericArraySource : public ArraySourceImpl<NumericArraySource<T>>
}
};
#if !__clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
template <typename Base>
struct ConstSource : public Base
{
@ -199,6 +204,10 @@ struct ConstSource : public Base
}
};
#if !__clang__
#pragma GCC diagnostic pop
#endif
struct StringSource
{
using Slice = NumericArraySlice<UInt8>;

View File

@ -29,7 +29,7 @@ public:
size_t buffer_size_ = DBMS_DEFAULT_BUFFER_SIZE);
/// Receives response from the server after sending all data.
void finalize();
void finalize() override;
};
}

View File

@ -101,7 +101,13 @@ inline bool readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp
{
++buf.position();
Int32 addition_exp = 0;
readIntText(addition_exp, buf);
if (!tryReadIntText(addition_exp, buf))
{
if constexpr (_throw_on_error)
throw Exception("Cannot parse exponent while reading decimal", ErrorCodes::CANNOT_PARSE_NUMBER);
else
return false;
}
exponent += addition_exp;
stop = true;
continue;

View File

@ -10,8 +10,8 @@ namespace DB
class ParserArray : public IParserBase
{
protected:
const char * getName() const { return "array"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "array"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -22,8 +22,8 @@ protected:
class ParserParenthesisExpression : public IParserBase
{
protected:
const char * getName() const { return "parenthesized expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "parenthesized expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -32,8 +32,8 @@ protected:
class ParserSubquery : public IParserBase
{
protected:
const char * getName() const { return "SELECT subquery"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "SELECT subquery"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -42,8 +42,8 @@ protected:
class ParserIdentifier : public IParserBase
{
protected:
const char * getName() const { return "identifier"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "identifier"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -52,16 +52,16 @@ protected:
class ParserCompoundIdentifier : public IParserBase
{
protected:
const char * getName() const { return "compound identifier"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "compound identifier"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/// Just *
class ParserAsterisk : public IParserBase
{
protected:
const char * getName() const { return "asterisk"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "asterisk"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Something like t.* or db.table.*
@ -69,8 +69,8 @@ protected:
class ParserQualifiedAsterisk : public IParserBase
{
protected:
const char * getName() const { return "qualified asterisk"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "qualified asterisk"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** COLUMNS('<regular expression>')
@ -78,8 +78,8 @@ protected:
class ParserColumnsMatcher : public IParserBase
{
protected:
const char * getName() const { return "COLUMNS matcher"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "COLUMNS matcher"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** A function, for example, f(x, y + 1, g(z)).
@ -93,16 +93,16 @@ class ParserFunction : public IParserBase
public:
ParserFunction(bool allow_function_parameters_ = true) : allow_function_parameters(allow_function_parameters_) {}
protected:
const char * getName() const { return "function"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "function"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
bool allow_function_parameters;
};
class ParserCodecDeclarationList : public IParserBase
{
protected:
const char * getName() const { return "codec declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "codec declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Parse compression codec
@ -111,8 +111,8 @@ protected:
class ParserCodec : public IParserBase
{
protected:
const char * getName() const { return "codec"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "codec"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserCastExpression : public IParserBase
@ -176,8 +176,8 @@ protected:
class ParserNull : public IParserBase
{
protected:
const char * getName() const { return "NULL"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "NULL"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -186,8 +186,8 @@ protected:
class ParserNumber : public IParserBase
{
protected:
const char * getName() const { return "number"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "number"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Unsigned integer, used in right hand side of tuple access operator (x.1).
@ -195,8 +195,8 @@ protected:
class ParserUnsignedInteger : public IParserBase
{
protected:
const char * getName() const { return "unsigned integer"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "unsigned integer"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -205,8 +205,8 @@ protected:
class ParserStringLiteral : public IParserBase
{
protected:
const char * getName() const { return "string literal"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "string literal"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -219,8 +219,8 @@ protected:
class ParserArrayOfLiterals : public IParserBase
{
protected:
const char * getName() const { return "array"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "array"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -229,8 +229,8 @@ protected:
class ParserLiteral : public IParserBase
{
protected:
const char * getName() const { return "literal"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "literal"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -246,8 +246,8 @@ private:
bool allow_alias_without_as_keyword;
const char * getName() const { return "alias"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "alias"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -257,8 +257,8 @@ private:
class ParserSubstitution : public IParserBase
{
protected:
const char * getName() const { return "substitution"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "substitution"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -267,8 +267,8 @@ protected:
class ParserExpressionElement : public IParserBase
{
protected:
const char * getName() const { return "element of expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "element of expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -283,8 +283,8 @@ protected:
ParserPtr elem_parser;
bool allow_alias_without_as_keyword;
const char * getName() const { return "element of expression with optional alias"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "element of expression with optional alias"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -296,8 +296,8 @@ protected:
class ParserOrderByElement : public IParserBase
{
protected:
const char * getName() const { return "element of ORDER BY expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "element of ORDER BY expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Parser for function with arguments like KEY VALUE (space separated)
@ -316,8 +316,8 @@ protected:
class ParserIdentifierWithOptionalParameters : public IParserBase
{
protected:
const char * getName() const { return "identifier with optional parameters"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "identifier with optional parameters"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Element of TTL expression - same as expression element, but in addition,
@ -326,8 +326,8 @@ protected:
class ParserTTLElement : public IParserBase
{
protected:
const char * getName() const { return "element of TTL expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "element of TTL expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -27,8 +27,8 @@ public:
{
}
protected:
const char * getName() const { return "list of elements"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "list of elements"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
private:
ParserPtr elem_parser;
ParserPtr separator_parser;
@ -63,9 +63,9 @@ public:
}
protected:
const char * getName() const { return "list, delimited by binary operators"; }
const char * getName() const override { return "list, delimited by binary operators"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -86,9 +86,9 @@ public:
}
protected:
const char * getName() const { return "list, delimited by operator of variable arity"; }
const char * getName() const override { return "list, delimited by operator of variable arity"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -110,8 +110,8 @@ public:
}
protected:
const char * getName() const { return "expression with prefix unary operator"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "expression with prefix unary operator"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -121,9 +121,9 @@ private:
static const char * operators[];
protected:
const char * getName() const { return "array element expression"; }
const char * getName() const override{ return "array element expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -133,9 +133,9 @@ private:
static const char * operators[];
protected:
const char * getName() const { return "tuple element expression"; }
const char * getName() const override { return "tuple element expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -146,9 +146,9 @@ private:
ParserPrefixUnaryOperatorExpression operator_parser {operators, std::make_unique<ParserTupleElementExpression>()};
protected:
const char * getName() const { return "unary minus expression"; }
const char * getName() const override { return "unary minus expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -159,9 +159,9 @@ private:
ParserLeftAssociativeBinaryOperatorList operator_parser {operators, std::make_unique<ParserUnaryMinusExpression>()};
protected:
const char * getName() const { return "multiplicative expression"; }
const char * getName() const override{ return "multiplicative expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -174,8 +174,8 @@ class ParserIntervalOperatorExpression : public IParserBase
protected:
ParserMultiplicativeExpression next_parser;
const char * getName() const { return "INTERVAL operator expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "INTERVAL operator expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -186,9 +186,9 @@ private:
ParserLeftAssociativeBinaryOperatorList operator_parser {operators, std::make_unique<ParserIntervalOperatorExpression>()};
protected:
const char * getName() const { return "additive expression"; }
const char * getName() const override{ return "additive expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -200,9 +200,9 @@ class ParserConcatExpression : public IParserBase
ParserVariableArityOperatorList operator_parser {"||", "concat", std::make_unique<ParserAdditiveExpression>()};
protected:
const char * getName() const { return "string concatenation expression"; }
const char * getName() const override { return "string concatenation expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -215,9 +215,9 @@ private:
ParserConcatExpression elem_parser;
protected:
const char * getName() const { return "BETWEEN expression"; }
const char * getName() const override { return "BETWEEN expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -228,9 +228,9 @@ private:
ParserLeftAssociativeBinaryOperatorList operator_parser {operators, std::make_unique<ParserBetweenExpression>()};
protected:
const char * getName() const { return "comparison expression"; }
const char * getName() const override{ return "comparison expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -257,9 +257,9 @@ private:
ParserPrefixUnaryOperatorExpression operator_parser {operators, std::make_unique<ParserNullityChecking>()};
protected:
const char * getName() const { return "logical-NOT expression"; }
const char * getName() const override{ return "logical-NOT expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -272,9 +272,9 @@ private:
ParserVariableArityOperatorList operator_parser {"AND", "and", std::make_unique<ParserLogicalNotExpression>()};
protected:
const char * getName() const { return "logical-AND expression"; }
const char * getName() const override { return "logical-AND expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -287,9 +287,9 @@ private:
ParserVariableArityOperatorList operator_parser {"OR", "or", std::make_unique<ParserLogicalAndExpression>()};
protected:
const char * getName() const { return "logical-OR expression"; }
const char * getName() const override { return "logical-OR expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return operator_parser.parse(pos, node, expected);
}
@ -305,9 +305,9 @@ private:
ParserLogicalOrExpression elem_parser;
protected:
const char * getName() const { return "expression with ternary operator"; }
const char * getName() const override { return "expression with ternary operator"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -317,9 +317,9 @@ private:
ParserTernaryOperatorExpression elem_parser;
protected:
const char * getName() const { return "lambda expression"; }
const char * getName() const override { return "lambda expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -333,9 +333,9 @@ public:
protected:
ParserPtr impl;
const char * getName() const { return "expression with optional alias"; }
const char * getName() const override { return "expression with optional alias"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
return impl->parse(pos, node, expected);
}
@ -352,8 +352,8 @@ public:
protected:
bool allow_alias_without_as_keyword;
const char * getName() const { return "list of expressions"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "list of expressions"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -365,16 +365,16 @@ public:
private:
ParserExpressionList nested_parser;
protected:
const char * getName() const { return "not empty list of expressions"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "not empty list of expressions"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserOrderByExpressionList : public IParserBase
{
protected:
const char * getName() const { return "order by expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "order by expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -399,8 +399,8 @@ protected:
class ParserTTLExpressionList : public IParserBase
{
protected:
const char * getName() const { return "ttl expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "ttl expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -35,7 +35,7 @@ public:
return res;
}
bool parse(Pos & pos, ASTPtr & node, Expected & expected);
bool parse(Pos & pos, ASTPtr & node, Expected & expected) override;
protected:
virtual bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) = 0;

View File

@ -27,16 +27,16 @@ namespace DB
class ParserAlterQuery : public IParserBase
{
protected:
const char * getName() const { return "ALTER query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "ALTER query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserAlterCommandList : public IParserBase
{
protected:
const char * getName() const { return "a list of ALTER commands"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "a list of ALTER commands"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
public:
bool is_live_view;
@ -48,8 +48,8 @@ public:
class ParserAlterCommand : public IParserBase
{
protected:
const char * getName() const { return "ALTER command"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "ALTER command"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
public:
bool is_live_view;
@ -62,8 +62,8 @@ public:
class ParserAssignment : public IParserBase
{
protected:
const char * getName() const { return "column assignment"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "column assignment"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -10,8 +10,8 @@ namespace DB
class ParserCheckQuery : public IParserBase
{
protected:
const char * getName() const { return "ALTER query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "ALTER query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -19,8 +19,8 @@ namespace DB
class ParserNestedTable : public IParserBase
{
protected:
const char * getName() const { return "nested table"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "nested table"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -33,16 +33,16 @@ protected:
class ParserIdentifierWithParameters : public IParserBase
{
protected:
const char * getName() const { return "identifier with parameters"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "identifier with parameters"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
template <typename NameParser>
class IParserNameTypePair : public IParserBase
{
protected:
const char * getName() const { return "name and type pair"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "name and type pair"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** The name and type are separated by a space. For example, URL String. */
@ -75,16 +75,16 @@ bool IParserNameTypePair<NameParser>::parseImpl(Pos & pos, ASTPtr & node, Expect
class ParserNameTypePairList : public IParserBase
{
protected:
const char * getName() const { return "name and type pair list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "name and type pair list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** List of table names. */
class ParserNameList : public IParserBase
{
protected:
const char * getName() const { return "name list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "name list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -99,9 +99,9 @@ public:
protected:
using ASTDeclarePtr = std::shared_ptr<ASTColumnDeclaration>;
const char * getName() const { return "column declaration"; }
const char * getName() const override{ return "column declaration"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
bool require_type = true;
};
@ -224,8 +224,8 @@ bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, ASTPtr & node, E
class ParserColumnDeclarationList : public IParserBase
{
protected:
const char * getName() const { return "column declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "column declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -284,8 +284,8 @@ protected:
class ParserStorage : public IParserBase
{
protected:
const char * getName() const { return "storage definition"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "storage definition"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** Query like this:
@ -308,32 +308,32 @@ protected:
class ParserCreateTableQuery : public IParserBase
{
protected:
const char * getName() const { return "CREATE TABLE or ATTACH TABLE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "CREATE TABLE or ATTACH TABLE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/// CREATE|ATTACH LIVE VIEW [IF NOT EXISTS] [db.]name [TO [db.]name] AS SELECT ...
class ParserCreateLiveViewQuery : public IParserBase
{
protected:
const char * getName() const { return "CREATE LIVE VIEW query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "CREATE LIVE VIEW query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/// CREATE|ATTACH DATABASE db [ENGINE = engine]
class ParserCreateDatabaseQuery : public IParserBase
{
protected:
const char * getName() const { return "CREATE DATABASE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "CREATE DATABASE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/// CREATE[OR REPLACE]|ATTACH [[MATERIALIZED] VIEW] | [VIEW]] [IF NOT EXISTS] [db.]name [TO [db.]name] [ENGINE = engine] [POPULATE] AS SELECT ...
class ParserCreateViewQuery : public IParserBase
{
protected:
const char * getName() const { return "CREATE VIEW query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "CREATE VIEW query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/// Parses complete dictionary create query. Uses ParserDictionary and
@ -372,8 +372,8 @@ protected:
class ParserCreateQuery : public IParserBase
{
protected:
const char * getName() const { return "CREATE TABLE or ATTACH TABLE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "CREATE TABLE or ATTACH TABLE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -13,8 +13,8 @@ namespace DB
class ParserDescribeTableQuery : public IParserBase
{
protected:
const char * getName() const { return "DESCRIBE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "DESCRIBE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -25,8 +25,8 @@ protected:
class ParserDictionaryAttributeDeclarationList : public IParserBase
{
protected:
const char * getName() const { return "attribute declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "attribute declaration list"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -19,8 +19,8 @@ namespace DB
class ParserDropQuery : public IParserBase
{
protected:
const char * getName() const { return "DROP query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "DROP query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
bool parseDropQuery(Pos & pos, ASTPtr & node, Expected & expected);
bool parseDetachQuery(Pos & pos, ASTPtr & node, Expected & expected);

View File

@ -12,8 +12,8 @@ namespace DB
class ParserOptimizeQuery : public IParserBase
{
protected:
const char * getName() const { return "OPTIMIZE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "OPTIMIZE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -14,8 +14,8 @@ namespace DB
class ParserRenameQuery : public IParserBase
{
protected:
const char * getName() const { return "RENAME query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "RENAME query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -11,8 +11,8 @@ namespace DB
class ParserRoleList : public IParserBase
{
protected:
const char * getName() const { return "RoleList"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "RoleList"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -12,8 +12,8 @@ namespace DB
class ParserSampleRatio : public IParserBase
{
protected:
const char * getName() const { return "Sample ratio or offset"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "Sample ratio or offset"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -14,9 +14,9 @@ namespace DB
class ParserShowProcesslistQuery : public IParserBase
{
protected:
const char * getName() const { return "SHOW PROCESSLIST query"; }
const char * getName() const override { return "SHOW PROCESSLIST query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
{
auto query = std::make_shared<ASTShowProcesslistQuery>();

View File

@ -14,8 +14,8 @@ namespace DB
class ParserShowTablesQuery : public IParserBase
{
protected:
const char * getName() const { return "SHOW [TEMPORARY] TABLES|DATABASES [[NOT] LIKE 'str'] [LIMIT expr]"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "SHOW [TEMPORARY] TABLES|DATABASES [[NOT] LIKE 'str'] [LIMIT expr]"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -11,8 +11,8 @@ namespace DB
class ParserTablesInSelectQuery : public IParserBase
{
protected:
const char * getName() const { return "table, table function, subquery or list of joined tables"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "table, table function, subquery or list of joined tables"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
@ -22,8 +22,8 @@ public:
ParserTablesInSelectQueryElement(bool is_first_) : is_first(is_first_) {}
protected:
const char * getName() const { return "table, table function, subquery or list of joined tables"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "table, table function, subquery or list of joined tables"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
private:
bool is_first;
@ -33,16 +33,16 @@ private:
class ParserTableExpression : public IParserBase
{
protected:
const char * getName() const { return "table or subquery or table function"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "table or subquery or table function"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserArrayJoin : public IParserBase
{
protected:
const char * getName() const { return "array join"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "array join"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};

View File

@ -11,8 +11,8 @@ namespace DB
class ParserUseQuery : public IParserBase
{
protected:
const char * getName() const { return "USE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override{ return "USE query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -23,8 +23,8 @@ namespace DB
class ParserWatchQuery : public IParserBase
{
protected:
const char * getName() const { return "WATCH query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
const char * getName() const override { return "WATCH query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -138,6 +138,9 @@ MergeTreeData::MergeTreeData(
, data_parts_by_state_and_info(data_parts_indexes.get<TagByStateAndInfo>())
, parts_mover(this)
{
if (relative_data_path.empty())
throw Exception("MergeTree storages require data path", ErrorCodes::INCORRECT_FILE_NAME);
const auto settings = getSettings();
setProperties(metadata);

View File

@ -394,7 +394,6 @@ void MergeTreeDataPart::remove() const
String to = full_path + "delete_tmp_" + name;
// TODO directory delete_tmp_<name> is never removed if server crashes before returning from this function
Poco::File from_dir{from};
Poco::File to_dir{to};

View File

@ -0,0 +1,7 @@
CREATE DATABASE memory_01069 ENGINE = Memory()
1
2
3
4
3
4

View File

@ -0,0 +1,18 @@
DROP DATABASE IF EXISTS memory_01069;
CREATE DATABASE memory_01069 ENGINE = Memory;
SHOW CREATE DATABASE memory_01069;
CREATE TABLE memory_01069.mt (n UInt8) ENGINE = MergeTree() ORDER BY n;
CREATE TABLE memory_01069.file (n UInt8) ENGINE = File(CSV);
INSERT INTO memory_01069.mt VALUES (1), (2);
INSERT INTO memory_01069.file VALUES (3), (4);
SELECT * FROM memory_01069.mt ORDER BY n;
SELECT * FROM memory_01069.file ORDER BY n;
DROP TABLE memory_01069.mt;
SELECT * FROM memory_01069.mt ORDER BY n; -- { serverError 60 }
SELECT * FROM memory_01069.file ORDER BY n;
DROP DATABASE memory_01069;

View File

@ -0,0 +1,8 @@
1
1
2
3
1 0
1 0
2 0
3 0

View File

@ -0,0 +1,15 @@
DROP TABLE IF EXISTS mv_source;
DROP TABLE IF EXISTS mv_target;
CREATE TABLE mv_source (`a` UInt64) ENGINE = MergeTree ORDER BY tuple();
CREATE TABLE mv_target (`a` UInt64) ENGINE = MergeTree ORDER BY tuple();
CREATE MATERIALIZED VIEW mv TO mv_target AS SELECT * FROM mv_source;
INSERT INTO mv_source VALUES (1);
ALTER TABLE mv_target ADD COLUMN b UInt8;
INSERT INTO mv_source VALUES (1),(2),(3);
SELECT * FROM mv ORDER BY a;
SELECT * FROM mv_target ORDER BY a;

View File

@ -0,0 +1,3 @@
\N 1
\N 1
\N 1

View File

@ -0,0 +1,7 @@
SELECT toDecimal32('e', 1); -- { serverError 72 }
SELECT toDecimal64('e', 2); -- { serverError 72 }
SELECT toDecimal128('e', 3); -- { serverError 72 }
SELECT toDecimal32OrNull('e', 1) x, isNull(x);
SELECT toDecimal64OrNull('e', 2) x, isNull(x);
SELECT toDecimal128OrNull('e', 3) x, isNull(x);

View File

@ -1,5 +1,6 @@
#!/usr/bin/python3
import os
import sys
import itertools
import clickhouse_driver
@ -12,6 +13,9 @@ import traceback
parser = argparse.ArgumentParser(description='Run performance test.')
# Explicitly decode files as UTF-8 because sometimes we have Russian characters in queries, and LANG=C is set.
parser.add_argument('file', metavar='FILE', type=argparse.FileType('r', encoding='utf-8'), nargs=1, help='test description file')
parser.add_argument('--host', nargs='*', default=['127.0.0.1', '127.0.0.1'])
parser.add_argument('--port', nargs='*', default=[9001, 9002])
parser.add_argument('--runs', type=int, default=int(os.environ.get('CHPC_RUNS', 7)))
args = parser.parse_args()
tree = et.parse(args.file[0])
@ -28,7 +32,7 @@ if infinite_sign is not None:
raise Exception('Looks like the test is infinite (sign 1)')
# Open connections
servers = [{'host': 'localhost', 'port': 9001, 'client_name': 'left'}, {'host': 'localhost', 'port': 9002, 'client_name': 'right'}]
servers = [{'host': host, 'port': port} for (host, port) in zip(args.host, args.port)]
connections = [clickhouse_driver.Client(**server) for server in servers]
# Check tables that should exist
@ -95,7 +99,7 @@ for q in test_queries:
# excessive data.
start_seconds = time.perf_counter()
server_seconds = 0
for run in range(0, 13):
for run in range(0, args.runs):
for conn_index, c in enumerate(connections):
res = c.execute(q)
print('query\t' + tsv_escape(q) + '\t' + str(run) + '\t' + str(conn_index) + '\t' + str(c.last_query.elapsed))

View File

@ -1,62 +1,209 @@
# How to Contribute to ClickHouse Documentation
# Contributing to ClickHouse Documentation
ClickHouse uses the "documentation as code" approach, so you can edit Markdown files in this folder from the GitHub web interface. Alternatively, fork the ClickHouse repository, edit, commit, push, and open a pull request.
## Why You Need to Document ClickHouse
At the moment documentation is bilingual in English and Russian. Try to keep all languages in sync if you can, but this is not strictly required. There are people who are responsible for monitoring language versions and syncing them. If you add a new article, you should also add it to `toc_{en,ru,zh,ja,fa}.yaml` files with the pages index.
The main reason is that ClickHouse is an open source project, and if you don't write the docs, nobody does. "Incomplete or Confusing Documentation" is the top complaint about open source software by the results of a [Github Open Source Survey](http://opensourcesurvey.org/2017/) of 2017. Documentation is highly valued but often overlooked. One of the most important contributions someone can make to an open source repository is a documentation update.
The master branch is then asynchronously published to the ClickHouse official website:
Many developers can say that the code is the best docs by itself, and they are right. But, ClickHouse is not a project for C++ developers. Most of its users don't know C++, and they can't understand the code quickly. ClickHouse is large enough to absorb almost any change without a noticeable trace. Nobody will find your very useful function, or an important setting, or a very informative new column in a system table if it is not referenced in the documentation.
* In English: https://clickhouse.yandex/docs/en/
* In Russian: https://clickhouse.yandex/docs/ru/
* In Chinese: https://clickhouse.yandex/docs/zh/
* In Japanese: https://clickhouse.yandex/docs/ja/
* In Farsi: https://clickhouse.yandex/docs/fa/
If you want to help ClickHouse with documentation you can face, for example, the following questions:
The infrastructure to build Markdown for publishing on the documentation website resides in the [tools](tools) folder. It has its own [README.md](tools/README.md) file with more details.
- "I don't know how to write."
# How to Write Content for ClickHouse Documentation
We have prepared some [recommendations](#what-to-write) for you.
## Target Audience
- "I know what I want to write, but I don't know how to contribute to docs."
When you write pretty much any text, the first thing you should think about is who will read it and which terms you should use for communicating with them.
Here are some [tips](#how-to-contribute).
ClickHouse can be directly used by all sorts of analysts and engineers. For generic parts of documentation (like the query language, tutorials or overviews), assume that the reader only has a basic technical background. For more technical sections (like articles that describe ClickHouse internals, guides for operating ClickHouse clusters, or rules for contributing to C++ code), you can use technical language and concepts.
Writing the docs is extremely useful for project's users and developers, and grows your karma.
## Specific Recommendations
**Contents**
* Documentation should make sense when you read it through from beginning to end. If you add new content, try to place it where the necessary concepts have already been explained.
* If a documentation section consists of many similar items, like functions or operators, try to order them from more generic (usable by a wide audience) to more specific (for specific use cases or application types). If several items are intended to be mostly used together, group them together in the documentation.
* Try to avoid slang. Use the most common and specific terms possible for everything. If some terms are used as synonyms, state this explicitly.
* All descriptions of functionality should be accompanied by examples. Basic examples are acceptable, but real world examples are welcome, too.
* Sensitive topics like politics, religion, race, and so on are strictly prohibited in documentation, examples, comments, and code.
* Proofread your text before publishing. Look for typos, missing punctuation, or repetitions that could be avoided.
* Try to avoid addressing the reader directly, although this is not strictly prohibited.
- [What is the ClickHouse Documentation](#clickhouse-docs)
- [How to Contribute to ClickHouse Documentation](#how-to-contribute)
- [Markdown Dialect Cheatsheet](#markdown-cheatsheet)
- [Adding a New File](#adding-a-new-file)
- [Adding a New Language](#adding-a-new-language)
- [How to Write Content for ClickHouse Documentation](#what-to-write)
- [Documentation for Different Audience](#target-audience)
- [Common Recommendations](#common-recommendations)
- [Description Templates](#templates)
- [How to Build Documentation](#how-to-build-docs)
# How to Add a New Language
<a name="clickhouse-docs"/>
## What is the ClickHouse Documentation
The documentation contains information about all the aspects of the ClickHouse lifecycle: developing, testing, installing, operating, and using. The base language of the documentation is English. The English version is the most actual. All other languages are supported as much as they can by contributors from different countries.
At the moment, [documentation](https://clickhouse.yandex/docs) exists in English, Russian, Chinese, Japanese, and Farsi. We store the documentation besides the ClickHouse source code in the [GitHub repository](https://github.com/ClickHouse/ClickHouse/tree/master/docs).
Each language lays in the corresponding folder. Files that are not translated from English are the symbolic links to the English ones.
<a name="how-to-contribute"/>
## How to Contribute to ClickHouse Documentation
You can contribute to the documentation in many ways, for example:
- Fork the ClickHouse repository, edit, commit, push, and open a pull request.
Add the `documentation` label to this pull request for proper automatic checks applying. If you have no permissions for adding labels, the reviewer of your PR adds it.
- Open a required file in the ClickHouse repository and edit it from the GitHub web interface.
You can do it on GitHub, or on the [ClickHouse Documentation](https://clickhouse.yandex/docs/en/) site. Each page of ClickHouse Documentation site contains an "Edit this page" (🖋) element in the upper right corner. Clicking this symbol, you get to the ClickHouse docs file opened for editing.
When you are saving a file, GitHub opens a pull-request for your contribution. Add the `documentation` label to this pull request for proper automatic checks applying. If you have no permissions for adding labels, the reviewer of your PR adds it.
Contribute all new information in English language. Other languages are translations from English.
<a name="markdown-cheatsheet"/>
### Markdown Dialect Cheatsheet
- Headings: Place them on a separate line and start with `# `, `## ` or `### `. Use the [Title Case](https://titlecase.com/) for them. Example:
```text
# The First Obligatory Title on a Page.
```
- Bold text: `**asterisks**` or `__underlines__`.
- Links: `[link text](uri)`. Examples:
- External link: `[ClickHouse repo](https://github.com/ClickHouse/ClickHouse)`
- Cross link: `[How to build docs](tools/README.md)`
- Images: `![Exclamation sign](uri)`. You can refer to local images as well as remote in internet.
- Lists: Lists can be of two types:
- `- unordered`: Each item starts from the `-`.
- `1. ordered`: Each item starts from the number.
A list must be separated from the text by an empty line. Nested lists must be indented with 4 spaces.
- Inline code: `` `in backticks` ``.
- Multiline code blocks:
<pre lang="no-highlight"><code>```lang_name
code
lines
```</code></pre>
- Note:
```text
!!! info "Header"
4 spaces indented text.
```
- Warning:
```text
!!! warning "Header"
4 spaces indented text.
```
- Text hidden behind a cut (single sting that opens on click):
```text
<details markdown="1"> <summary>Visible text</summary>
Hidden content.
</details>`.
```
- Colored text: `<span style="color: red;">text</span>`.
- Heading anchor to be linked to: `# Title {#anchor-name}`.
- Table:
```
| Header 1 | Header 2 | Header 3 |
| ----------- | ----------- | ----------- |
| Cell A1 | Cell A2 | Cell A3 |
| Cell B1 | Cell B2 | Cell B3 |
| Cell C1 | Cell C2 | Cell C3 |
```
<a name="adding-a-new-file"/>
### Adding a New File
When adding a new file:
- Make symbolic links for all other languages. You can use the following commands:
```bash
$ cd /ClickHouse/clone/directory/docs
$ ln -sr en/new/file.md lang/new/file.md
```
- Reference the file from `toc_{en,ru,zh,ja,fa}.yaml` files with the pages index.
<a name="adding-a-new-language"/>
### Adding a New Language
1. Create a new docs subfolder named using the [ISO-639-1 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
2. Add Markdown files with the translation, mirroring the folder structure of other languages.
3. Commit and open a pull request with the new content.
Some additional configuration has to be done to actually make a new language live on the official website, but it's not automated or documented yet, so we'll do it on our own after the pull request with the content is merged.
When everything is ready, we will add the new language to the website.
# Markdown Dialect Cheatsheet
<a name="what-to-write"/>
* Headings are on a separate line starting with `# `, `## ` or `### `.
* Bold is in `**asterisks**` or `__underlines__`.
* Links `[anchor](http://...)`, images `![with exclamation sign](http://...jpeg)`.
* Lists are on lines starting with `* unordered` or `1. ordered`, but there should be an empty line before the first list item. Sub-lists must be indented with 4 spaces.
* Inline code fragments are <code>&#96;in backticks&#96;</code>.
* Multiline code blocks are <code>&#96;&#96;&#96;in triple backtick quotes &#96;&#96;&#96;</code>.
* Brightly highlighted text starts with `!!! info "Header"`, followed by 4 spaces on the next line and content. For a warning, replace `info` with `warning`.
* Hidden block that opens on click: `<details markdown="1"> <summary>Header</summary> hidden content</details>`.
* Colored text: `<span style="color: red;">text</span>`.
* Heading anchor to be linked to: `Title {#anchor-name}`.
* Table:
```
| Header 1 | Header 2 | Header 3 |
| ----------- | ----------- | ----------- |
| Cell A1 | Cell A2 | Cell A3 |
| Cell B1 | Cell B2 | Cell B3 |
| Cell C1 | Cell C2 | Cell C3 |
```
## How to Write Content for ClickHouse Documentation
<a name="target-audience"/>
### Documentation for Different Audience
When writing documentation, think about people who read it. Each audience has specific requirements for terms they use in communications.
ClickHouse documentation can be divided by the audience for the following parts:
- Conceptual topics in [Introduction](https://clickhouse.yandex/docs/en/), tutorials and overviews, changelog.
These topics are for the most common auditory. When editing text in them, use the most common terms that are comfortable for the audience with basic technical skills.
- Query language reference and related topics.
These parts of the documentation are dedicated to those who use ClickHouse for data analysis. Carefully describe syntax, input, and output data for expressions. Don't forget the examples.
- Description of table engines and operation details.
Operation engineers who help data analysts to solve their tasks should know how to install/update a ClickHouse server, maintain the ClickHouse cluster, how to integrate it with other tools and systems, how to get the maximum performance of their entire environment.
- Developer's guides.
The documentation provides code writers with information about how to write code for ClickHouse and how to build it in different environments.
<a name="common-recommendations"/>
### Common Recommendations
- When searching for a position for your text, try to place it in the most anticipated place.
- Group entities. For example, if several functions solve similar tasks or belong to a specific group by use case or an application type, place them together.
- Try to avoid slang. Use the most common and specific terms possible. If some terms are used as synonyms, state this explicitly.
- Add examples for all the functionality. Add basic examples to show how the function works by itself. Add use case examples to show how the function participates in solving specific tasks.
- Any text concerning politics, religion, or other social related themes are strictly prohibited in all the ClickHouse texts.
- Proofread your text before publishing. Look for typos, missing punctuation, or repetitions that could be avoided.
<a name="templates"/>
### Description Templates
When writing docs, you can use prepared templates. Copy the code of a template and use it in your contribution. Sometimes you just need to change level of headers.
Templates:
- [Function](dscr-templates/template-function.md)
- [Setting](dscr-templates/template-setting.md)
- [Table engine](dscr-templates/template-table-engine.md)
- [System table](dscr-templates/template-system-table.md)
<a name="how-to-build-docs"/>
## How to Build Documentation
You can build your documentation manually by following the instructions in [docs/tools/README.md](docs/tools/README.md). Also, our CI runs the documentation build after the `documentation` label is added to PR. You can see the results of a build in the GitHub interface. If you have no permissions to add labels, a reviewer of your PR will add it.

View File

@ -0,0 +1,48 @@
## function-name {#function-name-in-lower-case}
Short description.
**Syntax** (without SELECT)
```sql
<function syntax>
```
Alias: `<alias name>`. (Optional)
More text (Optional).
**Parameters** (Optional)
- `x` — Description. [Type name](relative/path/to/type/dscr.md#type).
- `y` — Description. [Type name](relative/path/to/type/dscr.md#type).
**Returned value(s)**
- Returned values list.
Type: [Type](relative/path/to/type/dscr.md#type).
**Example**
The example must show usage and/or a use cases. The following text contains recommended parts of an example.
Input table (Optional):
```text
```
Query:
```sql
```
Result:
```text
```
**See Also** (Optional)
- [link](#)

View File

@ -0,0 +1,27 @@
## setting-name {#setting-name-in-lower-case}
Description.
For switcher setting, use the typical phrase: "Enables or disables something ...".
Possible values:
*For switcher setting:*
- 0 — Disabled.
- 1 — Enabled.
*For another setting (typical phrases):*
- Positive integer.
- 0 — Disabled or unlimited or smth. else.
Default value: `value`.
**Additional Info** (Optional)
The name of additional section can be any, for example **Usage**.
**See Also** (Optional)
- [link](#)

View File

@ -0,0 +1,21 @@
## system.table_name {#system_tables-table_name}
Description.
Columns:
- `column_name` ([data_type_name](data_type_uri)) — Description.
**Example**
```sql
SELECT * FROM system.table_name
```
```text
Some output. It shouldn't be long.
```
**See Also**
- [Article name](uri) — Some words about referenced information.

View File

@ -0,0 +1,51 @@
# EngineName
- What the engine does.
- Relations with other engines if they exist.
## Creating a Table
```
Syntax codeblock
```
**Engine Parameters**
**Query Clauses**
## Virtual columns
If they exist.
## Specifics and recommendations
Algorithms
Specifics of read/write processes
Examples of tasks
Recommendations for usage
Specifics of data storage
## Usage Example
The example must show usage and/or a use cases. The following text contains recommended parts of an example.
Input table:
```text
```
Query:
```sql
```
Result:
```text
```
Any text clarifying the example.
## See Also
- [link](#)

View File

@ -31,5 +31,7 @@ For compatibility with all MySQL clients, it is recommended to specify user pass
If user password is specified using [SHA256](../operations/settings/settings_users.md#password_sha256_hex), some clients won't be able to authenticate (mysqljs and old versions of command-line tool mysql).
Restrictions:
- prepared queries are not supported
- some data types are sent as strings

View File

@ -62,7 +62,7 @@ Password can be specified in plaintext or in SHA256 (hex format).
Example of how to generate a password from shell:
```
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | openssl dgst -sha1 -binary | openssl dgst -sha1
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
```
The first line of the result is the password. The second line is the corresponding double SHA1 hash.

View File

@ -31,5 +31,7 @@ mysql>
В случае указания пароля с помощью [SHA256](../operations/settings/settings_users.md#password_sha256_hex) некоторые клиенты не смогут пройти аутентификацию (mysqljs и старые версии стандартного клиента mysql).
Ограничения:
- не поддерживаются подготовленные запросы
- некоторые типы данных отправляются как строки

View File

@ -62,7 +62,7 @@
Пример создания пароля в командной строке:
```
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | openssl dgst -sha1 -binary | openssl dgst -sha1
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
```
Первая строка результата — пароль. Вторая строка — соответствующий ему двойной хэш SHA1.

View File

@ -12,9 +12,9 @@
class KillingErrorHandler : public Poco::ErrorHandler
{
public:
void exception(const Poco::Exception &) { std::terminate(); }
void exception(const std::exception &) { std::terminate(); }
void exception() { std::terminate(); }
void exception(const Poco::Exception &) override { std::terminate(); }
void exception(const std::exception &) override { std::terminate(); }
void exception() override { std::terminate(); }
};
@ -23,9 +23,9 @@ public:
class ServerErrorHandler : public Poco::ErrorHandler
{
public:
void exception(const Poco::Exception &) { logException(); }
void exception(const std::exception &) { logException(); }
void exception() { logException(); }
void exception(const Poco::Exception &) override { logException(); }
void exception(const std::exception &) override { logException(); }
void exception() override { logException(); }
private:
Logger * log = &Logger::get("ServerErrorHandler");

View File

@ -1,49 +1,46 @@
#pragma once
#include <sstream>
#include <mysqlxx/Types.h>
#include <Poco/Exception.h>
#include <mysqlxx/Types.h>
namespace mysqlxx
{
/** Общий класс исключений, которые могут быть выкинуты функциями из библиотеки.
* Функции code() и errnum() возвращают номер ошибки MySQL. (см. mysqld_error.h)
*/
/// Common exception class for MySQL library. Functions code() and errnum() return error numbers from MySQL, for details see mysqld_error.h
struct Exception : public Poco::Exception
{
Exception(const std::string & msg, int code = 0) : Poco::Exception(msg, code) {}
int errnum() const { return code(); }
const char * name() const throw() { return "mysqlxx::Exception"; }
const char * className() const throw() { return "mysqlxx::Exception"; }
const char * name() const throw() override { return "mysqlxx::Exception"; }
const char * className() const throw() override { return "mysqlxx::Exception"; }
};
/// Не удалось соединиться с сервером.
/// Cannot connect to MySQL server
struct ConnectionFailed : public Exception
{
ConnectionFailed(const std::string & msg, int code = 0) : Exception(msg, code) {}
const char * name() const throw() { return "mysqlxx::ConnectionFailed"; }
const char * className() const throw() { return "mysqlxx::ConnectionFailed"; }
const char * name() const throw() override { return "mysqlxx::ConnectionFailed"; }
const char * className() const throw() override { return "mysqlxx::ConnectionFailed"; }
};
/// Запрос содержит ошибку.
/// Erroneous query.
struct BadQuery : public Exception
{
BadQuery(const std::string & msg, int code = 0) : Exception(msg, code) {}
const char * name() const throw() { return "mysqlxx::BadQuery"; }
const char * className() const throw() { return "mysqlxx::BadQuery"; }
const char * name() const throw() override { return "mysqlxx::BadQuery"; }
const char * className() const throw() override { return "mysqlxx::BadQuery"; }
};
/// Невозможно распарсить значение.
/// Value parsing failure
struct CannotParseValue : public Exception
{
CannotParseValue(const std::string & msg, int code = 0) : Exception(msg, code) {}
const char * name() const throw() { return "mysqlxx::CannotParseValue"; }
const char * className() const throw() { return "mysqlxx::CannotParseValue"; }
const char * name() const throw() override { return "mysqlxx::CannotParseValue"; }
const char * className() const throw() override { return "mysqlxx::CannotParseValue"; }
};