mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
Pretty print tuples in CREATE TABLE statements
This commit is contained in:
parent
67bbe6fe98
commit
4b68ba23c0
@ -264,7 +264,11 @@ int mainEntryClickHouseFormat(int argc, char ** argv)
|
|||||||
if (!backslash)
|
if (!backslash)
|
||||||
{
|
{
|
||||||
WriteBufferFromOwnString str_buf;
|
WriteBufferFromOwnString str_buf;
|
||||||
formatAST(*res, str_buf, hilite, oneline || approx_query_length < max_line_length);
|
oneline = oneline || approx_query_length < max_line_length;
|
||||||
|
IAST::FormatSettings settings(str_buf, oneline, hilite);
|
||||||
|
settings.show_secrets = true;
|
||||||
|
settings.print_pretty_type_names = !oneline;
|
||||||
|
res->format(settings);
|
||||||
|
|
||||||
if (insert_query_payload)
|
if (insert_query_payload)
|
||||||
{
|
{
|
||||||
|
@ -331,7 +331,11 @@ ASTPtr ClientBase::parseQuery(const char *& pos, const char * end, const Setting
|
|||||||
{
|
{
|
||||||
output_stream << std::endl;
|
output_stream << std::endl;
|
||||||
WriteBufferFromOStream res_buf(output_stream, 4096);
|
WriteBufferFromOStream res_buf(output_stream, 4096);
|
||||||
formatAST(*res, res_buf);
|
IAST::FormatSettings format_settings(res_buf, /* one_line */ false);
|
||||||
|
format_settings.hilite = true;
|
||||||
|
format_settings.show_secrets = true;
|
||||||
|
format_settings.print_pretty_type_names = true;
|
||||||
|
res->format(format_settings);
|
||||||
res_buf.finalize();
|
res_buf.finalize();
|
||||||
output_stream << std::endl << std::endl;
|
output_stream << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ void BaseExternalTable::parseStructureFromStructureField(const std::string & arg
|
|||||||
/// We use `formatWithPossiblyHidingSensitiveData` instead of `getColumnNameWithoutAlias` because `column->type` is an ASTFunction.
|
/// We use `formatWithPossiblyHidingSensitiveData` instead of `getColumnNameWithoutAlias` because `column->type` is an ASTFunction.
|
||||||
/// `getColumnNameWithoutAlias` will return name of the function with `(arguments)` even if arguments is empty.
|
/// `getColumnNameWithoutAlias` will return name of the function with `(arguments)` even if arguments is empty.
|
||||||
if (column)
|
if (column)
|
||||||
structure.emplace_back(column->name, column->type->formatWithPossiblyHidingSensitiveData(0, true, true));
|
structure.emplace_back(column->name, column->type->formatWithPossiblyHidingSensitiveData(0, true, true, false));
|
||||||
else
|
else
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: expected column definition, got {}", child->formatForErrorMessage());
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: expected column definition, got {}", child->formatForErrorMessage());
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ void BaseExternalTable::parseStructureFromTypesField(const std::string & argumen
|
|||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error);
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error);
|
||||||
|
|
||||||
for (size_t i = 0; i < type_list_raw->children.size(); ++i)
|
for (size_t i = 0; i < type_list_raw->children.size(); ++i)
|
||||||
structure.emplace_back("_" + toString(i + 1), type_list_raw->children[i]->formatWithPossiblyHidingSensitiveData(0, true, true));
|
structure.emplace_back("_" + toString(i + 1), type_list_raw->children[i]->formatWithPossiblyHidingSensitiveData(0, true, true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseExternalTable::initSampleBlock()
|
void BaseExternalTable::initSampleBlock()
|
||||||
|
@ -882,7 +882,7 @@ class IColumn;
|
|||||||
M(Bool, use_json_alias_for_old_object_type, false, "When enabled, JSON type alias will create old experimental Object type instead of a new JSON type", 0) \
|
M(Bool, use_json_alias_for_old_object_type, false, "When enabled, JSON type alias will create old experimental Object type instead of a new JSON type", 0) \
|
||||||
M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0) \
|
M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0) \
|
||||||
M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0) \
|
M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0) \
|
||||||
M(Bool, print_pretty_type_names, true, "Print pretty type names in DESCRIBE query and toTypeName() function", 0) \
|
M(Bool, print_pretty_type_names, true, "Print pretty type names in the DESCRIBE query and `toTypeName` function", 0) \
|
||||||
M(Bool, create_table_empty_primary_key_by_default, false, "Allow to create *MergeTree tables with empty primary key when ORDER BY and PRIMARY KEY not specified", 0) \
|
M(Bool, create_table_empty_primary_key_by_default, false, "Allow to create *MergeTree tables with empty primary key when ORDER BY and PRIMARY KEY not specified", 0) \
|
||||||
M(Bool, allow_named_collection_override_by_default, true, "Allow named collections' fields override by default.", 0) \
|
M(Bool, allow_named_collection_override_by_default, true, "Allow named collections' fields override by default.", 0) \
|
||||||
M(SQLSecurityType, default_normal_view_sql_security, SQLSecurityType::INVOKER, "Allows to set a default value for SQL SECURITY option when creating a normal view.", 0) \
|
M(SQLSecurityType, default_normal_view_sql_security, SQLSecurityType::INVOKER, "Allows to set a default value for SQL SECURITY option when creating a normal view.", 0) \
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <Common/quoteString.h>
|
#include <Common/quoteString.h>
|
||||||
|
|
||||||
#include <IO/WriteHelpers.h>
|
#include <IO/WriteHelpers.h>
|
||||||
#include <IO/Operators.h>
|
|
||||||
|
|
||||||
#include <DataTypes/IDataType.h>
|
#include <DataTypes/IDataType.h>
|
||||||
#include <DataTypes/DataTypeCustom.h>
|
#include <DataTypes/DataTypeCustom.h>
|
||||||
|
@ -504,7 +504,7 @@ void DatabaseOnDisk::renameTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// It returns create table statement (even if table is detached)
|
/// It returns the create table statement (even if table is detached)
|
||||||
ASTPtr DatabaseOnDisk::getCreateTableQueryImpl(const String & table_name, ContextPtr, bool throw_on_error) const
|
ASTPtr DatabaseOnDisk::getCreateTableQueryImpl(const String & table_name, ContextPtr, bool throw_on_error) const
|
||||||
{
|
{
|
||||||
ASTPtr ast;
|
ASTPtr ast;
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
max_query_size = settings.max_query_size;
|
max_query_size = settings.max_query_size;
|
||||||
max_parser_depth = settings.max_parser_depth;
|
max_parser_depth = settings.max_parser_depth;
|
||||||
max_parser_backtracks = settings.max_parser_backtracks;
|
max_parser_backtracks = settings.max_parser_backtracks;
|
||||||
|
print_pretty_type_names = settings.print_pretty_type_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getName() const override { return name; }
|
String getName() const override { return name; }
|
||||||
@ -138,7 +139,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatAST(*ast, buf, /*hilite*/ false, /*single_line*/ output_formatting == OutputFormatting::SingleLine);
|
IAST::FormatSettings settings(buf, output_formatting == OutputFormatting::SingleLine, /*hilite*/ false);
|
||||||
|
settings.show_secrets = true;
|
||||||
|
settings.print_pretty_type_names = print_pretty_type_names;
|
||||||
|
ast->format(settings);
|
||||||
|
|
||||||
auto formatted = buf.stringView();
|
auto formatted = buf.stringView();
|
||||||
|
|
||||||
const size_t res_data_new_size = res_data_size + formatted.size() + 1;
|
const size_t res_data_new_size = res_data_size + formatted.size() + 1;
|
||||||
@ -165,6 +170,7 @@ private:
|
|||||||
size_t max_query_size;
|
size_t max_query_size;
|
||||||
size_t max_parser_depth;
|
size_t max_parser_depth;
|
||||||
size_t max_parser_backtracks;
|
size_t max_parser_backtracks;
|
||||||
|
bool print_pretty_type_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,10 @@ QueryPipeline InterpreterShowCreateQuery::executeImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MutableColumnPtr column = ColumnString::create();
|
MutableColumnPtr column = ColumnString::create();
|
||||||
column->insert(format({.ctx = getContext(), .query = *create_query, .one_line = false}));
|
column->insert(format({
|
||||||
|
.ctx = getContext(),
|
||||||
|
.query = *create_query,
|
||||||
|
.one_line = false}));
|
||||||
|
|
||||||
return QueryPipeline(std::make_shared<SourceFromSingleChunk>(Block{{
|
return QueryPipeline(std::make_shared<SourceFromSingleChunk>(Block{{
|
||||||
std::move(column),
|
std::move(column),
|
||||||
|
@ -25,7 +25,8 @@ inline String format(const SecretHidingFormatSettings & settings)
|
|||||||
&& settings.ctx->getSettingsRef().format_display_secrets_in_show_and_select
|
&& settings.ctx->getSettingsRef().format_display_secrets_in_show_and_select
|
||||||
&& settings.ctx->getAccess()->isGranted(AccessType::displaySecretsInShowAndSelect);
|
&& settings.ctx->getAccess()->isGranted(AccessType::displaySecretsInShowAndSelect);
|
||||||
|
|
||||||
return settings.query.formatWithPossiblyHidingSensitiveData(settings.max_length, settings.one_line, show_secrets);
|
return settings.query.formatWithPossiblyHidingSensitiveData(
|
||||||
|
settings.max_length, settings.one_line, show_secrets, settings.ctx->getSettingsRef().print_pretty_type_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -66,17 +66,13 @@ void ASTColumnDeclaration::formatImpl(const FormatSettings & format_settings, Fo
|
|||||||
{
|
{
|
||||||
frame.need_parens = false;
|
frame.need_parens = false;
|
||||||
|
|
||||||
/// We have to always backquote column names to avoid ambiguouty with INDEX and other declarations in CREATE query.
|
/// We have to always backquote column names to avoid ambiguity with INDEX and other declarations in CREATE query.
|
||||||
format_settings.ostr << backQuote(name);
|
format_settings.ostr << backQuote(name);
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
{
|
{
|
||||||
format_settings.ostr << ' ';
|
format_settings.ostr << ' ';
|
||||||
|
type->formatImpl(format_settings, state, frame);
|
||||||
FormatStateStacked type_frame = frame;
|
|
||||||
type_frame.indent = 0;
|
|
||||||
|
|
||||||
type->formatImpl(format_settings, state, type_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null_modifier)
|
if (null_modifier)
|
||||||
|
@ -40,12 +40,21 @@ void ASTDataType::formatImpl(const FormatSettings & settings, FormatState & stat
|
|||||||
{
|
{
|
||||||
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
||||||
|
|
||||||
for (size_t i = 0, size = arguments->children.size(); i < size; ++i)
|
if (!settings.one_line && settings.print_pretty_type_names && name == "Tuple")
|
||||||
{
|
{
|
||||||
if (i != 0)
|
++frame.indent;
|
||||||
settings.ostr << ", ";
|
std::string indent_str = settings.one_line ? "" : "\n" + std::string(4 * frame.indent, ' ');
|
||||||
|
for (size_t i = 0, size = arguments->children.size(); i < size; ++i)
|
||||||
arguments->children[i]->formatImpl(settings, state, frame);
|
{
|
||||||
|
if (i != 0)
|
||||||
|
settings.ostr << ',';
|
||||||
|
settings.ostr << indent_str;
|
||||||
|
arguments->children[i]->formatImpl(settings, state, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arguments->formatImpl(settings, state, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
||||||
|
@ -42,7 +42,8 @@ void ASTExpressionList::formatImpl(const FormatSettings & settings, FormatState
|
|||||||
|
|
||||||
void ASTExpressionList::formatImplMultiline(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
void ASTExpressionList::formatImplMultiline(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
||||||
{
|
{
|
||||||
std::string indent_str = "\n" + std::string(4 * (frame.indent + 1), ' ');
|
++frame.indent;
|
||||||
|
std::string indent_str = "\n" + std::string(4 * frame.indent, ' ');
|
||||||
|
|
||||||
if (frame.expression_list_prepend_whitespace)
|
if (frame.expression_list_prepend_whitespace)
|
||||||
{
|
{
|
||||||
@ -50,8 +51,6 @@ void ASTExpressionList::formatImplMultiline(const FormatSettings & settings, For
|
|||||||
settings.ostr << ' ';
|
settings.ostr << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
++frame.indent;
|
|
||||||
|
|
||||||
for (size_t i = 0, size = children.size(); i < size; ++i)
|
for (size_t i = 0, size = children.size(); i < size; ++i)
|
||||||
{
|
{
|
||||||
if (i && separator)
|
if (i && separator)
|
||||||
|
@ -23,12 +23,8 @@ ASTPtr ASTNameTypePair::clone() const
|
|||||||
|
|
||||||
void ASTNameTypePair::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
void ASTNameTypePair::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
||||||
{
|
{
|
||||||
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
|
settings.ostr << backQuoteIfNeed(name) << ' ';
|
||||||
|
|
||||||
settings.ostr << indent_str << backQuoteIfNeed(name) << ' ';
|
|
||||||
type->formatImpl(settings, state, frame);
|
type->formatImpl(settings, state, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,11 +165,12 @@ size_t IAST::checkDepthImpl(size_t max_depth) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
String IAST::formatWithPossiblyHidingSensitiveData(size_t max_length, bool one_line, bool show_secrets) const
|
String IAST::formatWithPossiblyHidingSensitiveData(size_t max_length, bool one_line, bool show_secrets, bool print_pretty_type_names) const
|
||||||
{
|
{
|
||||||
WriteBufferFromOwnString buf;
|
WriteBufferFromOwnString buf;
|
||||||
FormatSettings settings(buf, one_line);
|
FormatSettings settings(buf, one_line);
|
||||||
settings.show_secrets = show_secrets;
|
settings.show_secrets = show_secrets;
|
||||||
|
settings.print_pretty_type_names = print_pretty_type_names;
|
||||||
format(settings);
|
format(settings);
|
||||||
return wipeSensitiveDataAndCutToLength(buf.str(), max_length);
|
return wipeSensitiveDataAndCutToLength(buf.str(), max_length);
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,7 @@ public:
|
|||||||
bool show_secrets; /// Show secret parts of the AST (e.g. passwords, encryption keys).
|
bool show_secrets; /// Show secret parts of the AST (e.g. passwords, encryption keys).
|
||||||
char nl_or_ws; /// Newline or whitespace.
|
char nl_or_ws; /// Newline or whitespace.
|
||||||
LiteralEscapingStyle literal_escaping_style;
|
LiteralEscapingStyle literal_escaping_style;
|
||||||
|
bool print_pretty_type_names;
|
||||||
|
|
||||||
explicit FormatSettings(
|
explicit FormatSettings(
|
||||||
WriteBuffer & ostr_,
|
WriteBuffer & ostr_,
|
||||||
@ -209,7 +210,8 @@ public:
|
|||||||
bool always_quote_identifiers_ = false,
|
bool always_quote_identifiers_ = false,
|
||||||
IdentifierQuotingStyle identifier_quoting_style_ = IdentifierQuotingStyle::Backticks,
|
IdentifierQuotingStyle identifier_quoting_style_ = IdentifierQuotingStyle::Backticks,
|
||||||
bool show_secrets_ = true,
|
bool show_secrets_ = true,
|
||||||
LiteralEscapingStyle literal_escaping_style_ = LiteralEscapingStyle::Regular)
|
LiteralEscapingStyle literal_escaping_style_ = LiteralEscapingStyle::Regular,
|
||||||
|
bool print_pretty_type_names_ = false)
|
||||||
: ostr(ostr_)
|
: ostr(ostr_)
|
||||||
, one_line(one_line_)
|
, one_line(one_line_)
|
||||||
, hilite(hilite_)
|
, hilite(hilite_)
|
||||||
@ -218,6 +220,7 @@ public:
|
|||||||
, show_secrets(show_secrets_)
|
, show_secrets(show_secrets_)
|
||||||
, nl_or_ws(one_line ? ' ' : '\n')
|
, nl_or_ws(one_line ? ' ' : '\n')
|
||||||
, literal_escaping_style(literal_escaping_style_)
|
, literal_escaping_style(literal_escaping_style_)
|
||||||
|
, print_pretty_type_names(print_pretty_type_names_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +233,7 @@ public:
|
|||||||
, show_secrets(other.show_secrets)
|
, show_secrets(other.show_secrets)
|
||||||
, nl_or_ws(other.nl_or_ws)
|
, nl_or_ws(other.nl_or_ws)
|
||||||
, literal_escaping_style(other.literal_escaping_style)
|
, literal_escaping_style(other.literal_escaping_style)
|
||||||
|
, print_pretty_type_names(other.print_pretty_type_names)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +255,7 @@ public:
|
|||||||
/// The state that is copied when each node is formatted. For example, nesting level.
|
/// The state that is copied when each node is formatted. For example, nesting level.
|
||||||
struct FormatStateStacked
|
struct FormatStateStacked
|
||||||
{
|
{
|
||||||
UInt8 indent = 0;
|
UInt16 indent = 0;
|
||||||
bool need_parens = false;
|
bool need_parens = false;
|
||||||
bool expression_list_always_start_on_new_line = false; /// Line feed and indent before expression list even if it's of single element.
|
bool expression_list_always_start_on_new_line = false; /// Line feed and indent before expression list even if it's of single element.
|
||||||
bool expression_list_prepend_whitespace = false; /// Prepend whitespace (if it is required)
|
bool expression_list_prepend_whitespace = false; /// Prepend whitespace (if it is required)
|
||||||
@ -274,7 +278,7 @@ public:
|
|||||||
|
|
||||||
/// Secrets are displayed regarding show_secrets, then SensitiveDataMasker is applied.
|
/// Secrets are displayed regarding show_secrets, then SensitiveDataMasker is applied.
|
||||||
/// You can use Interpreters/formatWithPossiblyHidingSecrets.h for convenience.
|
/// You can use Interpreters/formatWithPossiblyHidingSecrets.h for convenience.
|
||||||
String formatWithPossiblyHidingSensitiveData(size_t max_length, bool one_line, bool show_secrets) const;
|
String formatWithPossiblyHidingSensitiveData(size_t max_length, bool one_line, bool show_secrets, bool print_pretty_type_names) const;
|
||||||
|
|
||||||
/** formatForLogging and formatForErrorMessage always hide secrets. This inconsistent
|
/** formatForLogging and formatForErrorMessage always hide secrets. This inconsistent
|
||||||
* behaviour is due to the fact such functions are called from Client which knows nothing about
|
* behaviour is due to the fact such functions are called from Client which knows nothing about
|
||||||
@ -283,12 +287,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
String formatForLogging(size_t max_length = 0) const
|
String formatForLogging(size_t max_length = 0) const
|
||||||
{
|
{
|
||||||
return formatWithPossiblyHidingSensitiveData(max_length, true, false);
|
return formatWithPossiblyHidingSensitiveData(max_length, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatForErrorMessage() const
|
String formatForErrorMessage() const
|
||||||
{
|
{
|
||||||
return formatWithPossiblyHidingSensitiveData(0, true, false);
|
return formatWithPossiblyHidingSensitiveData(0, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool hasSecretParts() const { return childrenHaveSecretParts(); }
|
virtual bool hasSecretParts() const { return childrenHaveSecretParts(); }
|
||||||
|
Loading…
Reference in New Issue
Block a user