This commit is contained in:
kssenii 2021-08-19 15:18:39 +00:00
parent 7be06f894e
commit 512d66a088
4 changed files with 120 additions and 120 deletions

View File

@ -162,8 +162,10 @@ ExpressionAnalyzer::ExpressionAnalyzer(
analyzeAggregation(); analyzeAggregation();
} }
static ASTPtr checkPositionalArgument(ASTPtr argument, const NamesAndTypesList & columns) static ASTPtr checkPositionalArgument(ASTPtr argument, const ASTSelectQuery * select_query, ASTSelectQuery::Expression expression)
{ {
auto columns = select_query->select()->children;
/// Case when GROUP BY element is position. /// Case when GROUP BY element is position.
/// Do not consider case when GROUP BY element is not a literal, but expression, even if all values are constants. /// Do not consider case when GROUP BY element is not a literal, but expression, even if all values are constants.
if (auto * ast_literal = typeid_cast<const ASTLiteral *>(argument.get())) if (auto * ast_literal = typeid_cast<const ASTLiteral *>(argument.get()))
@ -174,9 +176,19 @@ static ASTPtr checkPositionalArgument(ASTPtr argument, const NamesAndTypesList &
auto pos = ast_literal->value.get<UInt64>(); auto pos = ast_literal->value.get<UInt64>();
if ((0 < pos) && (pos <= columns.size())) if ((0 < pos) && (pos <= columns.size()))
{ {
const auto & column_name = std::next(columns.begin(), pos - 1)->name; --pos;
return std::make_shared<ASTIdentifier>(column_name); const auto & column = columns[pos];
if (const auto * literal_ast = typeid_cast<const ASTIdentifier *>(column.get()))
{
return std::make_shared<ASTIdentifier>(literal_ast->name());
} }
else
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal value for positional argument in {}",
ASTSelectQuery::expressionToString(expression));
}
}
/// Do not throw if out of bounds, see appendUnusedGroupByColumn.
} }
} }
return nullptr; return nullptr;
@ -257,7 +269,6 @@ void ExpressionAnalyzer::analyzeAggregation()
{ {
NameSet unique_keys; NameSet unique_keys;
ASTs & group_asts = select_query->groupBy()->children; ASTs & group_asts = select_query->groupBy()->children;
const auto & columns = syntax->source_columns;
for (ssize_t i = 0; i < ssize_t(group_asts.size()); ++i) for (ssize_t i = 0; i < ssize_t(group_asts.size()); ++i)
{ {
@ -266,7 +277,7 @@ void ExpressionAnalyzer::analyzeAggregation()
if (getContext()->getSettingsRef().enable_positional_arguments) if (getContext()->getSettingsRef().enable_positional_arguments)
{ {
auto new_argument = checkPositionalArgument(group_asts[i], columns); auto new_argument = checkPositionalArgument(group_asts[i], select_query, ASTSelectQuery::Expression::GROUP_BY);
if (new_argument) if (new_argument)
group_asts[i] = new_argument; group_asts[i] = new_argument;
} }
@ -1252,7 +1263,6 @@ ActionsDAGPtr SelectQueryExpressionAnalyzer::appendOrderBy(ExpressionActionsChai
bool with_fill = false; bool with_fill = false;
NameSet order_by_keys; NameSet order_by_keys;
const auto & columns = syntax->source_columns;
for (auto & child : select_query->orderBy()->children) for (auto & child : select_query->orderBy()->children)
{ {
@ -1262,7 +1272,7 @@ ActionsDAGPtr SelectQueryExpressionAnalyzer::appendOrderBy(ExpressionActionsChai
if (getContext()->getSettingsRef().enable_positional_arguments) if (getContext()->getSettingsRef().enable_positional_arguments)
{ {
auto new_argument = checkPositionalArgument(ast->children.at(0), columns); auto new_argument = checkPositionalArgument(ast->children.at(0), select_query, ASTSelectQuery::Expression::ORDER_BY);
if (new_argument) if (new_argument)
ast->children[0] = new_argument; ast->children[0] = new_argument;
} }
@ -1317,13 +1327,12 @@ bool SelectQueryExpressionAnalyzer::appendLimitBy(ExpressionActionsChain & chain
} }
auto & children = select_query->limitBy()->children; auto & children = select_query->limitBy()->children;
const auto & columns = syntax->source_columns;
for (size_t i = 0; i < children.size(); ++i) for (size_t i = 0; i < children.size(); ++i)
{ {
if (getContext()->getSettingsRef().enable_positional_arguments) if (getContext()->getSettingsRef().enable_positional_arguments)
{ {
auto new_argument = checkPositionalArgument(children[i], columns); auto new_argument = checkPositionalArgument(children[i], select_query, ASTSelectQuery::Expression::LIMIT_BY);
if (new_argument) if (new_argument)
children[i] = new_argument; children[i] = new_argument;
} }

View File

@ -35,6 +35,43 @@ public:
SETTINGS SETTINGS
}; };
static String expressionToString(Expression expr)
{
switch (expr)
{
case Expression::WITH:
return "WITH";
case Expression::SELECT:
return "SELECT";
case Expression::TABLES:
return "TABLES";
case Expression::PREWHERE:
return "PREWHERE";
case Expression::WHERE:
return "WHERE";
case Expression::GROUP_BY:
return "GROUP BY";
case Expression::HAVING:
return "HAVING";
case Expression::WINDOW:
return "WINDOW";
case Expression::ORDER_BY:
return "ORDER BY";
case Expression::LIMIT_BY_OFFSET:
return "LIMIT BY OFFSET";
case Expression::LIMIT_BY_LENGTH:
return "LIMIT BY LENGTH";
case Expression::LIMIT_BY:
return "LIMIT BY";
case Expression::LIMIT_OFFSET:
return "LIMIT OFFSET";
case Expression::LIMIT_LENGTH:
return "LIMIT LENGTH";
case Expression::SETTINGS:
return "SETTINGS";
}
}
/** Get the text that identifies this element. */ /** Get the text that identifies this element. */
String getID(char) const override { return "SelectQuery"; } String getID(char) const override { return "SelectQuery"; }

View File

@ -1,90 +1,50 @@
-- { echo } -- { echo }
set enable_positional_arguments = 1; select x3, x2, x1 from test order by 1;
drop table if exists test; 1 100 100
create table test (col1 Int32, col2 Int32, col3 Int32) engine = Memory(); 10 1 10
insert into test select number, number, 5 from numbers(2); 100 10 1
insert into test select number, number, 4 from numbers(2); select x3, x2, x1 from test order by x3;
insert into test select number, number, 3 from numbers(2); 1 100 100
insert into test select number, number, 2 from numbers(2); 10 1 10
insert into test select number, number, 1 from numbers(2); 100 10 1
select * from test where col1 = 1 order by 3 desc; select x3, x2, x1 from test order by 1 desc;
1 1 5 100 10 1
1 1 4 10 1 10
1 1 3 1 100 100
1 1 2 select x3, x2, x1 from test order by x3 desc;
1 1 1 100 10 1
select * from test where col2 = 1 order by 3 asc; 10 1 10
1 1 1 1 100 100
1 1 2 insert into test values (1, 10, 200), (10, 1, 200), (100, 100, 1);
1 1 3 select x3, x2 from test group by x3, x2;
1 1 4 200 1
1 1 5 10 1
insert into test select number, number+1, 1 from numbers(2); 200 10
insert into test select number, number+1, 2 from numbers(2); 1 100
insert into test select number, number+1, 3 from numbers(2); 100 10
insert into test select number, number+1, 4 from numbers(2); select x3, x2 from test group by 1, 2;
insert into test select number, number+1, 5 from numbers(2); 200 1
select * from test order by col1, col2, col3 asc limit 2 by col2; 10 1
0 0 1 200 10
0 0 2 1 100
0 1 1 100 10
0 1 2 select x1, x2, x3 from test order by x3 limit 1 by x3;
1 2 1 100 100 1
1 2 2 10 1 10
select * from test order by 1, 2, 3 asc limit 2 by 2; 1 10 100
0 0 1 1 10 200
0 0 2 select x1, x2, x3 from test order by 3 limit 1 by 3;
0 1 1 100 100 1
0 1 2 10 1 10
1 2 1 1 10 100
1 2 2 1 10 200
select col1, col2 from test group by col1, col2 order by col1, col2; select x1, x2, x3 from test order by x3 limit 1 by x1;
0 0 100 100 1
0 1 10 1 10
1 1 1 10 100
1 2 select x1, x2, x3 from test order by 3 limit 1 by 1;
select col1, col2 from test group by 1, 2 order by 1, 2; 100 100 1
0 0 10 1 10
0 1 1 10 100
1 1 select max(x3), max(x2), max(x1) from test group by 1; -- { serverError 43 }
1 2 select max(x1) from test order by 1; -- { serverError 43 }
select col2, col3 from test group by col3, col2 order by col3, col2;
0 1
1 1
2 1
0 2
1 2
2 2
0 3
1 3
2 3
0 4
1 4
2 4
0 5
1 5
2 5
select col2, col3 from test group by 3, 2 order by 3, 2;
0 1
1 1
2 1
0 2
1 2
2 2
0 3
1 3
2 3
0 4
1 4
2 4
0 5
1 5
2 5
select col2 from test group by 2 order by 2;
0
1
2
select col2 + 100 from test group by 2 order by 2;
100
101
102

View File

@ -1,32 +1,26 @@
-- { echo }
set enable_positional_arguments = 1; set enable_positional_arguments = 1;
drop table if exists test; drop table if exists test;
create table test (col1 Int32, col2 Int32, col3 Int32) engine = Memory(); create table test(x1 Int, x2 Int, x3 Int) engine=Memory();
insert into test values (1, 10, 100), (10, 1, 10), (100, 100, 1);
insert into test select number, number, 5 from numbers(2); -- { echo }
insert into test select number, number, 4 from numbers(2); select x3, x2, x1 from test order by 1;
insert into test select number, number, 3 from numbers(2); select x3, x2, x1 from test order by x3;
insert into test select number, number, 2 from numbers(2);
insert into test select number, number, 1 from numbers(2);
select * from test where col1 = 1 order by 3 desc; select x3, x2, x1 from test order by 1 desc;
select * from test where col2 = 1 order by 3 asc; select x3, x2, x1 from test order by x3 desc;
insert into test select number, number+1, 1 from numbers(2); insert into test values (1, 10, 200), (10, 1, 200), (100, 100, 1);
insert into test select number, number+1, 2 from numbers(2); select x3, x2 from test group by x3, x2;
insert into test select number, number+1, 3 from numbers(2); select x3, x2 from test group by 1, 2;
insert into test select number, number+1, 4 from numbers(2);
insert into test select number, number+1, 5 from numbers(2);
select * from test order by col1, col2, col3 asc limit 2 by col2; select x1, x2, x3 from test order by x3 limit 1 by x3;
select * from test order by 1, 2, 3 asc limit 2 by 2; select x1, x2, x3 from test order by 3 limit 1 by 3;
select x1, x2, x3 from test order by x3 limit 1 by x1;
select x1, x2, x3 from test order by 3 limit 1 by 1;
select col1, col2 from test group by col1, col2 order by col1, col2; select max(x3), max(x2), max(x1) from test group by 1; -- { serverError 43 }
select col1, col2 from test group by 1, 2 order by 1, 2; select max(x1) from test order by 1; -- { serverError 43 }
select col2, col3 from test group by col3, col2 order by col3, col2;
select col2, col3 from test group by 3, 2 order by 3, 2;
select col2 from test group by 2 order by 2;
select col2 + 100 from test group by 2 order by 2;