Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clickhouse-3775 #2572

Merged
merged 3 commits into from
Jun 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions dbms/src/Interpreters/ExpressionAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1983,26 +1983,34 @@ bool ExpressionAnalyzer::isThereArrayJoin(const ASTPtr & ast)
void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack,
ProjectionManipulatorPtr projection_manipulator)
{
String ast_column_name;
auto getColumnName = [&ast, &ast_column_name]()
{
if (ast_column_name.empty())
ast_column_name = ast->getColumnName();

return ast_column_name;
};

/// If the result of the calculation already exists in the block.
if ((typeid_cast<ASTFunction *>(ast.get()) || typeid_cast<ASTLiteral *>(ast.get()))
&& projection_manipulator->tryToGetFromUpperProjection(ast->getColumnName()))
&& projection_manipulator->tryToGetFromUpperProjection(getColumnName()))
return;

if (ASTIdentifier * node = typeid_cast<ASTIdentifier *>(ast.get()))
if (typeid_cast<ASTIdentifier *>(ast.get()))
{
std::string name = node->getColumnName();
if (!only_consts && !projection_manipulator->tryToGetFromUpperProjection(ast->getColumnName()))
if (!only_consts && !projection_manipulator->tryToGetFromUpperProjection(getColumnName()))
{
/// The requested column is not in the block.
/// If such a column exists in the table, then the user probably forgot to surround it with an aggregate function or add it to GROUP BY.

bool found = false;
for (const auto & column_name_type : source_columns)
if (column_name_type.name == name)
if (column_name_type.name == getColumnName())
found = true;

if (found)
throw Exception("Column " + name + " is not under aggregate function and not in GROUP BY.",
throw Exception("Column " + getColumnName() + " is not under aggregate function and not in GROUP BY.",
ErrorCodes::NOT_AN_AGGREGATE);
}
}
Expand All @@ -2021,7 +2029,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
getActionsImpl(arg, no_subqueries, only_consts, actions_stack, projection_manipulator);
if (!only_consts)
{
String result_name = projection_manipulator->getColumnName(node->getColumnName());
String result_name = projection_manipulator->getColumnName(getColumnName());
actions_stack.addAction(ExpressionAction::copyColumn(projection_manipulator->getColumnName(arg->getColumnName()), result_name));
NameSet joined_columns;
joined_columns.insert(result_name);
Expand Down Expand Up @@ -2049,7 +2057,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
/// We are in the part of the tree that we are not going to compute. You just need to define types.
/// Do not subquery and create sets. We insert an arbitrary column of the correct type.
ColumnWithTypeAndName fake_column;
fake_column.name = projection_manipulator->getColumnName(node->getColumnName());
fake_column.name = projection_manipulator->getColumnName(getColumnName());
fake_column.type = std::make_shared<DataTypeUInt8>();
actions_stack.addAction(ExpressionAction::addColumn(fake_column, projection_manipulator->getProjectionSourceColumn(), false));
getActionsImpl(node->arguments->children.at(0), no_subqueries, only_consts, actions_stack,
Expand All @@ -2065,15 +2073,15 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
{
actions_stack.addAction(ExpressionAction::addColumn(ColumnWithTypeAndName(
ColumnConst::create(ColumnUInt8::create(1, 1), 1), std::make_shared<DataTypeUInt8>(),
projection_manipulator->getColumnName(node->getColumnName())), projection_manipulator->getProjectionSourceColumn(), false));
projection_manipulator->getColumnName(getColumnName())), projection_manipulator->getProjectionSourceColumn(), false));
return;
}

if (AggregateFunctionFactory::instance().isAggregateFunctionName(node->name))
return;

const FunctionBuilderPtr & function_builder = FunctionFactory::instance().get(node->name, context);
auto projection_action = getProjectionAction(node->name, actions_stack, projection_manipulator, node->getColumnName(), context);
auto projection_action = getProjectionAction(node->name, actions_stack, projection_manipulator, getColumnName(), context);

Names argument_names;
DataTypes argument_types;
Expand All @@ -2085,6 +2093,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
for (size_t arg = 0; arg < node->arguments->children.size(); ++arg)
{
auto & child = node->arguments->children[arg];
auto child_column_name = child->getColumnName();

ASTFunction * lambda = typeid_cast<ASTFunction *>(child.get());
if (lambda && lambda->name == "lambda")
Expand Down Expand Up @@ -2115,7 +2124,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
if (!set->empty())
column.name = getUniqueName(actions_stack.getSampleBlock(), "__set");
else
column.name = child->getColumnName();
column.name = child_column_name;

column.name = projection_manipulator->getColumnName(column.name);

Expand All @@ -2135,8 +2144,8 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
projection_action->preArgumentAction();
getActionsImpl(child, no_subqueries, only_consts, actions_stack,
projection_manipulator);
std::string name = projection_manipulator->getColumnName(child->getColumnName());
projection_action->postArgumentAction(child->getColumnName());
std::string name = projection_manipulator->getColumnName(child_column_name);
projection_action->postArgumentAction(child_column_name);
if (actions_stack.getSampleBlock().has(name))
{
argument_types.push_back(actions_stack.getSampleBlock().getByName(name).type);
Expand Down Expand Up @@ -2239,7 +2248,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
actions_stack.addAction(
ExpressionAction::applyFunction(function_builder,
argument_names,
projection_manipulator->getColumnName(node->getColumnName()),
projection_manipulator->getColumnName(getColumnName()),
projection_manipulator->getProjectionSourceColumn()));
}
}
Expand All @@ -2251,7 +2260,7 @@ void ExpressionAnalyzer::getActionsImpl(const ASTPtr & ast, bool no_subqueries,
ColumnWithTypeAndName column;
column.column = type->createColumnConst(1, convertFieldToType(node->value, *type));
column.type = type;
column.name = node->getColumnName();
column.name = getColumnName();

actions_stack.addAction(ExpressionAction::addColumn(column, "", false));
projection_manipulator->tryToGetFromUpperProjection(column.name);
Expand Down
21 changes: 21 additions & 0 deletions dbms/src/Parsers/ASTAsterisk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <Parsers/ASTAsterisk.h>
#include <IO/WriteBuffer.h>

namespace DB
{

ASTPtr ASTAsterisk::clone() const
{
auto clone = std::make_shared<ASTAsterisk>(*this);
clone->cloneChildren();
return std::move(clone);
}

void ASTAsterisk::appendColumnName(WriteBuffer & ostr) const { ostr.write('*'); }

void ASTAsterisk::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const
{
settings.ostr << "*";
}

}
14 changes: 3 additions & 11 deletions dbms/src/Parsers/ASTAsterisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,11 @@ class ASTAsterisk : public IAST
{
public:
String getID() const override { return "Asterisk"; }
ASTPtr clone() const override
{
auto clone = std::make_shared<ASTAsterisk>(*this);
clone->cloneChildren();
return std::move(clone);
}
String getColumnName() const override { return "*"; }
ASTPtr clone() const override;
void appendColumnName(WriteBuffer & ostr) const override;

protected:
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override
{
settings.ostr << "*";
}
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override;
};

}
26 changes: 12 additions & 14 deletions dbms/src/Parsers/ASTFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,30 @@
namespace DB
{

String ASTFunction::getColumnNameImpl() const
void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const
{
WriteBufferFromOwnString wb;
writeString(name, wb);
writeString(name, ostr);

if (parameters)
{
writeChar('(', wb);
for (ASTs::const_iterator it = parameters->children.begin(); it != parameters->children.end(); ++it)
writeChar('(', ostr);
for (auto it = parameters->children.begin(); it != parameters->children.end(); ++it)
{
if (it != parameters->children.begin())
writeCString(", ", wb);
writeString((*it)->getColumnName(), wb);
writeCString(", ", ostr);
(*it)->appendColumnName(ostr);
}
writeChar(')', wb);
writeChar(')', ostr);
}

writeChar('(', wb);
for (ASTs::const_iterator it = arguments->children.begin(); it != arguments->children.end(); ++it)
writeChar('(', ostr);
for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it)
{
if (it != arguments->children.begin())
writeCString(", ", wb);
writeString((*it)->getColumnName(), wb);
writeCString(", ", ostr);
(*it)->appendColumnName(ostr);
}
writeChar(')', wb);
return wb.str();
writeChar(')', ostr);
}

/** Get the text that identifies this element. */
Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Parsers/ASTFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ASTFunction : public ASTWithAlias

protected:
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
String getColumnNameImpl() const override;
void appendColumnNameImpl(WriteBuffer & ostr) const override;
};


Expand Down
5 changes: 5 additions & 0 deletions dbms/src/Parsers/ASTIdentifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ void ASTIdentifier::formatImplWithoutAlias(const FormatSettings & settings, Form
}
}

void ASTIdentifier::appendColumnNameImpl(WriteBuffer & ostr) const
{
writeString(name, ostr);
}

}
2 changes: 1 addition & 1 deletion dbms/src/Parsers/ASTIdentifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class ASTIdentifier : public ASTWithAlias

protected:
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
String getColumnNameImpl() const override { return name; }
void appendColumnNameImpl(WriteBuffer & ostr) const override;
};

}
16 changes: 11 additions & 5 deletions dbms/src/Parsers/ASTLiteral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
namespace DB
{


String ASTLiteral::getColumnNameImpl() const
void ASTLiteral::appendColumnNameImpl(WriteBuffer & ostr) const
{
/// Special case for very large arrays. Instead of listing all elements, will use hash of them.
/// (Otherwise column name will be too long, that will lead to significant slowdown of expression analysis.)
Expand All @@ -19,10 +18,17 @@ String ASTLiteral::getColumnNameImpl() const
applyVisitor(FieldVisitorHash(hash), value);
UInt64 low, high;
hash.get128(low, high);
return "__array_" + toString(low) + "_" + toString(high);
}

return applyVisitor(FieldVisitorToString(), value);
writeCString("__array_", ostr);
writeText(low, ostr);
ostr.write('_');
writeText(high, ostr);
}
else
{
String column_name = applyVisitor(FieldVisitorToString(), value);
writeString(column_name, ostr);
}
}

}
2 changes: 1 addition & 1 deletion dbms/src/Parsers/ASTLiteral.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ASTLiteral : public ASTWithAlias
settings.ostr << applyVisitor(FieldVisitorToString(), value);
}

String getColumnNameImpl() const override;
void appendColumnNameImpl(WriteBuffer & ostr) const override;
};

}
6 changes: 4 additions & 2 deletions dbms/src/Parsers/ASTQualifiedAsterisk.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#include <Parsers/ASTQualifiedAsterisk.h>
#include <IO/WriteHelpers.h>

namespace DB
{

String ASTQualifiedAsterisk::getColumnName() const
void ASTQualifiedAsterisk::appendColumnName(WriteBuffer & ostr) const
{
const auto & qualifier = children.at(0);
return qualifier->getColumnName() + ".*";
qualifier->appendColumnName(ostr);
writeCString(".*", ostr);
}

void ASTQualifiedAsterisk::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Parsers/ASTQualifiedAsterisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ASTQualifiedAsterisk : public IAST
clone->cloneChildren();
return std::move(clone);
}
String getColumnName() const override;
void appendColumnName(WriteBuffer & ostr) const override;

protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
Expand Down
22 changes: 19 additions & 3 deletions dbms/src/Parsers/ASTSubquery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,30 @@
namespace DB
{

String ASTSubquery::getColumnNameImpl() const
void ASTSubquery::appendColumnNameImpl(WriteBuffer & ostr) const
{
/// This is a hack. We use alias, if available, because otherwise tree could change during analysis.
if (!alias.empty())
return alias;
writeString(alias, ostr);

Hash hash = getTreeHash();
return "__subquery_" + toString(hash.first) + "_" + toString(hash.second);
writeCString("__subquery_", ostr);
writeText(hash.first, ostr);
ostr.write('_');
writeText(hash.second, ostr);
}

void ASTSubquery::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
std::string indent_str = settings.one_line ? "" : std::string(4u * frame.indent, ' ');
std::string nl_or_nothing = settings.one_line ? "" : "\n";

settings.ostr << nl_or_nothing << indent_str << "(" << nl_or_nothing;
FormatStateStacked frame_nested = frame;
frame_nested.need_parens = false;
++frame_nested.indent;
children[0]->formatImpl(settings, state, frame_nested);
settings.ostr << nl_or_nothing << indent_str << ")";
}

}
Expand Down
16 changes: 2 additions & 14 deletions dbms/src/Parsers/ASTSubquery.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,8 @@ class ASTSubquery : public ASTWithAlias
}

protected:
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
{
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
std::string nl_or_nothing = settings.one_line ? "" : "\n";

settings.ostr << nl_or_nothing << indent_str << "(" << nl_or_nothing;
FormatStateStacked frame_nested = frame;
frame_nested.need_parens = false;
++frame_nested.indent;
children[0]->formatImpl(settings, state, frame_nested);
settings.ostr << nl_or_nothing << indent_str << ")";
}

String getColumnNameImpl() const override;
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
void appendColumnNameImpl(WriteBuffer & ostr) const override;
};

}
8 changes: 8 additions & 0 deletions dbms/src/Parsers/ASTWithAlias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ void ASTWithAlias::formatImpl(const FormatSettings & settings, FormatState & sta
}
}

void ASTWithAlias::appendColumnName(WriteBuffer & ostr) const
{
if (prefer_alias_to_column_name && !alias.empty())
writeString(alias, ostr);
else
appendColumnNameImpl(ostr);
}

}
6 changes: 3 additions & 3 deletions dbms/src/Parsers/ASTWithAlias.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class ASTWithAlias : public IAST

using IAST::IAST;

String getColumnName() const override final { return prefer_alias_to_column_name && !alias.empty() ? alias : getColumnNameImpl(); }
String getAliasOrColumnName() const override { return alias.empty() ? getColumnNameImpl() : alias; }
void appendColumnName(WriteBuffer & ostr) const final;
String getAliasOrColumnName() const override { return alias.empty() ? getColumnName() : alias; }
String tryGetAlias() const override { return alias; }
void setAlias(const String & to) override { alias = to; }

Expand All @@ -31,7 +31,7 @@ class ASTWithAlias : public IAST
virtual void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const = 0;

protected:
virtual String getColumnNameImpl() const = 0;
virtual void appendColumnNameImpl(WriteBuffer & ostr) const = 0;
};

/// helper for setting aliases and chaining result to other functions
Expand Down
Loading