diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 2aed174c088..e5122720380 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -464,6 +464,7 @@ class IColumn; M(UnionMode, union_default_mode, UnionMode::Unspecified, "Set default Union Mode in SelectWithUnion query. Possible values: empty string, 'ALL', 'DISTINCT'. If empty, query without Union Mode will throw exception.", 0) \ M(Bool, optimize_aggregators_of_group_by_keys, true, "Eliminates min/max/any/anyLast aggregators of GROUP BY keys in SELECT section", 0) \ M(Bool, optimize_group_by_function_keys, true, "Eliminates functions of other keys in GROUP BY section", 0) \ + M(Bool, legacy_column_name_of_tuple_literal, false, "List all names of element of large tuple literals in their column names instead of hash. This settings exists only for compatibity reasons. It makes sense to set to 'true', while doing rolling update of cluster from version lower than 21.7 to higher.", 0) \ \ M(Bool, query_plan_enable_optimizations, true, "Apply optimizations to query plan", 0) \ M(UInt64, query_plan_max_optimizations_to_apply, 10000, "Limit the total number of optimizations applied to query plan. If zero, ignored. If limit reached, throw exception", 0) \ diff --git a/src/Interpreters/ActionsVisitor.cpp b/src/Interpreters/ActionsVisitor.cpp index 066a5d20223..3dc4172db54 100644 --- a/src/Interpreters/ActionsVisitor.cpp +++ b/src/Interpreters/ActionsVisitor.cpp @@ -348,7 +348,7 @@ SetPtr makeExplicitSet( const ASTPtr & left_arg = args.children.at(0); const ASTPtr & right_arg = args.children.at(1); - auto column_name = left_arg->getColumnName(); + auto column_name = left_arg->getColumnName(context->getSettingsRef()); const auto & dag_node = actions.findInIndex(column_name); const DataTypePtr & left_arg_type = dag_node.result_type; @@ -638,7 +638,7 @@ std::optional ActionsMatcher::getNameAndTypeFromAST(const ASTPt { // If the argument is a literal, we generated a unique column name for it. // Use it instead of a generic display name. - auto child_column_name = ast->getColumnName(); + auto child_column_name = ast->getColumnName(data.getContext()->getSettingsRef()); const auto * as_literal = ast->as(); if (as_literal) { @@ -700,7 +700,7 @@ ASTs ActionsMatcher::doUntuple(const ASTFunction * function, ActionsMatcher::Dat func->setAlias(data.getUniqueName("_ut_" + name)); auto function_builder = FunctionFactory::instance().get(func->name, data.getContext()); - data.addFunction(function_builder, {tuple_name_type->name, literal->getColumnName()}, func->getColumnName()); + data.addFunction(function_builder, {tuple_name_type->name, literal->getColumnName(data.getContext()->getSettingsRef())}, func->getColumnName(data.getContext()->getSettingsRef())); columns.push_back(std::move(func)); } @@ -737,7 +737,7 @@ void ActionsMatcher::visit(ASTExpressionList & expression_list, const ASTPtr &, void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr & ast, Data & data) { - auto column_name = ast->getColumnName(); + auto column_name = ast->getColumnName(data.getContext()->getSettingsRef()); if (data.hasColumn(column_name)) return; @@ -763,7 +763,7 @@ void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr & ast, void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & data) { - auto column_name = ast->getColumnName(); + auto column_name = ast->getColumnName(data.getContext()->getSettingsRef()); if (data.hasColumn(column_name)) return; @@ -779,7 +779,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & ASTPtr arg = node.arguments->children.at(0); visit(arg, data); if (!data.only_consts) - data.addArrayJoin(arg->getColumnName(), column_name); + data.addArrayJoin(arg->getColumnName(data.getContext()->getSettingsRef()), column_name); return; } @@ -801,7 +801,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & /// 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 replace "in*" function to "in*IgnoreSet". - auto argument_name = node.arguments->children.at(0)->getColumnName(); + auto argument_name = node.arguments->children.at(0)->getColumnName(data.getContext()->getSettingsRef()); data.addFunction( FunctionFactory::instance().get(node.name + "IgnoreSet", data.getContext()), @@ -930,7 +930,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & if (!prepared_set->empty()) column.name = data.getUniqueName("__set"); else - column.name = child->getColumnName(); + column.name = child->getColumnName(data.getContext()->getSettingsRef()); if (!data.hasColumn(column.name)) { @@ -1009,7 +1009,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & visit(lambda->arguments->children.at(1), data); auto lambda_dag = data.actions_stack.popLevel(); - String result_name = lambda->arguments->children.at(1)->getColumnName(); + String result_name = lambda->arguments->children.at(1)->getColumnName(data.getContext()->getSettingsRef()); lambda_dag->removeUnusedActions(Names(1, result_name)); auto lambda_actions = std::make_shared( @@ -1024,7 +1024,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & if (findColumn(required_arg, lambda_arguments) == lambda_arguments.end()) captured.push_back(required_arg); - /// We can not name `getColumnName()`, + /// We can not name `getColumnName(data.getContext()->getSettingsRef())`, /// because it does not uniquely define the expression (the types of arguments can be different). String lambda_name = data.getUniqueName("__lambda"); @@ -1054,7 +1054,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & if (arguments_present) { /// Calculate column name here again, because AST may be changed here (in case of untuple). - data.addFunction(function_builder, argument_names, ast->getColumnName()); + data.addFunction(function_builder, argument_names, ast->getColumnName(data.getContext()->getSettingsRef())); } } @@ -1068,7 +1068,7 @@ void ActionsMatcher::visit(const ASTLiteral & literal, const ASTPtr & /* ast */, // AST here? Anyway, do not modify the column name if it is set already. if (literal.unique_column_name.empty()) { - const auto default_name = literal.getColumnName(); + const auto default_name = literal.getColumnName(data.getContext()->getSettingsRef()); const auto & index = data.actions_stack.getLastActionsIndex(); const auto * existing_column = index.tryGetNode(default_name); @@ -1148,7 +1148,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data, bool no_su } /// We get the stream of blocks for the subquery. Create Set and put it in place of the subquery. - String set_id = right_in_operand->getColumnName(); + String set_id = right_in_operand->getColumnName(data.getContext()->getSettingsRef()); SubqueryForSet & subquery_for_set = data.subqueries_for_sets[set_id]; @@ -1184,7 +1184,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data, bool no_su { const auto & last_actions = data.actions_stack.getLastActions(); const auto & index = data.actions_stack.getLastActionsIndex(); - if (index.contains(left_in_operand->getColumnName())) + if (index.contains(left_in_operand->getColumnName(data.getContext()->getSettingsRef()))) /// An explicit enumeration of values in parentheses. return makeExplicitSet(&node, last_actions, false, data.getContext(), data.set_size_limit, data.prepared_sets); else diff --git a/src/Interpreters/ExpressionAnalyzer.cpp b/src/Interpreters/ExpressionAnalyzer.cpp index 216d9fecf5b..1ec88fe9389 100644 --- a/src/Interpreters/ExpressionAnalyzer.cpp +++ b/src/Interpreters/ExpressionAnalyzer.cpp @@ -244,7 +244,7 @@ void ExpressionAnalyzer::analyzeAggregation() ssize_t size = group_asts.size(); getRootActionsNoMakeSet(group_asts[i], true, temp_actions, false); - const auto & column_name = group_asts[i]->getColumnName(); + const auto & column_name = group_asts[i]->getColumnName(getContext()->getSettingsRef()); const auto * node = temp_actions->tryFindInIndex(column_name); if (!node) throw Exception("Unknown identifier (in GROUP BY): " + column_name, ErrorCodes::UNKNOWN_IDENTIFIER); @@ -398,7 +398,7 @@ void SelectQueryExpressionAnalyzer::makeSetsForIndex(const ASTPtr & node) auto temp_actions = std::make_shared(columns_after_join); getRootActions(left_in_operand, true, temp_actions); - if (temp_actions->tryFindInIndex(left_in_operand->getColumnName())) + if (temp_actions->tryFindInIndex(left_in_operand->getColumnName(getContext()->getSettingsRef()))) makeExplicitSet(func, *temp_actions, true, getContext(), settings.size_limits_for_set, prepared_sets); } } @@ -446,7 +446,7 @@ bool ExpressionAnalyzer::makeAggregateDescriptions(ActionsDAGPtr & actions) if (node->arguments) getRootActionsNoMakeSet(node->arguments, true, actions); - aggregate.column_name = node->getColumnName(); + aggregate.column_name = node->getColumnName(getContext()->getSettingsRef()); const ASTs & arguments = node->arguments ? node->arguments->children : ASTs(); aggregate.argument_names.resize(arguments.size()); @@ -454,7 +454,7 @@ bool ExpressionAnalyzer::makeAggregateDescriptions(ActionsDAGPtr & actions) for (size_t i = 0; i < arguments.size(); ++i) { - const std::string & name = arguments[i]->getColumnName(); + const std::string & name = arguments[i]->getColumnName(getContext()->getSettingsRef()); const auto * dag_node = actions->tryFindInIndex(name); if (!dag_node) { @@ -647,7 +647,7 @@ void ExpressionAnalyzer::makeWindowDescriptions(ActionsDAGPtr actions) WindowFunctionDescription window_function; window_function.function_node = function_node; window_function.column_name - = window_function.function_node->getColumnName(); + = window_function.function_node->getColumnName(getContext()->getSettingsRef()); window_function.function_parameters = window_function.function_node->parameters ? getAggregateFunctionParametersArray( @@ -666,7 +666,7 @@ void ExpressionAnalyzer::makeWindowDescriptions(ActionsDAGPtr actions) window_function.argument_names.resize(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { - const std::string & name = arguments[i]->getColumnName(); + const std::string & name = arguments[i]->getColumnName(getContext()->getSettingsRef()); const auto * node = actions->tryFindInIndex(name); if (!node) @@ -964,7 +964,7 @@ ActionsDAGPtr SelectQueryExpressionAnalyzer::appendPrewhere( auto & step = chain.lastStep(sourceColumns()); getRootActions(select_query->prewhere(), only_types, step.actions()); - String prewhere_column_name = select_query->prewhere()->getColumnName(); + String prewhere_column_name = select_query->prewhere()->getColumnName(getContext()->getSettingsRef()); step.addRequiredOutput(prewhere_column_name); const auto & node = step.actions()->findInIndex(prewhere_column_name); @@ -1061,7 +1061,7 @@ bool SelectQueryExpressionAnalyzer::appendWhere(ExpressionActionsChain & chain, getRootActions(select_query->where(), only_types, step.actions()); - auto where_column_name = select_query->where()->getColumnName(); + auto where_column_name = select_query->where()->getColumnName(getContext()->getSettingsRef()); step.addRequiredOutput(where_column_name); const auto & node = step.actions()->findInIndex(where_column_name); @@ -1086,7 +1086,7 @@ bool SelectQueryExpressionAnalyzer::appendGroupBy(ExpressionActionsChain & chain ASTs asts = select_query->groupBy()->children; for (const auto & ast : asts) { - step.addRequiredOutput(ast->getColumnName()); + step.addRequiredOutput(ast->getColumnName(getContext()->getSettingsRef())); getRootActions(ast, only_types, step.actions()); } @@ -1114,7 +1114,7 @@ void SelectQueryExpressionAnalyzer::appendAggregateFunctionsArguments(Expression for (const auto & name : desc.argument_names) step.addRequiredOutput(name); - /// Collect aggregates removing duplicates by node.getColumnName() + /// Collect aggregates removing duplicates by node.getColumnName(getContext()->getSettingsRef()) /// It's not clear why we recollect aggregates (for query parts) while we're able to use previously collected ones (for entire query) /// @note The original recollection logic didn't remove duplicates. GetAggregatesVisitor::Data data; @@ -1169,7 +1169,7 @@ void SelectQueryExpressionAnalyzer::appendWindowFunctionsArguments( // (2b) Required function argument columns. for (const auto & a : f.function_node->arguments->children) { - step.addRequiredOutput(a->getColumnName()); + step.addRequiredOutput(a->getColumnName(getContext()->getSettingsRef())); } } @@ -1191,7 +1191,7 @@ bool SelectQueryExpressionAnalyzer::appendHaving(ExpressionActionsChain & chain, ExpressionActionsChain::Step & step = chain.lastStep(aggregated_columns); getRootActionsForHaving(select_query->having(), only_types, step.actions()); - step.addRequiredOutput(select_query->having()->getColumnName()); + step.addRequiredOutput(select_query->having()->getColumnName(getContext()->getSettingsRef())); return true; } @@ -1215,7 +1215,7 @@ void SelectQueryExpressionAnalyzer::appendSelect(ExpressionActionsChain & chain, continue; } - step.addRequiredOutput(child->getColumnName()); + step.addRequiredOutput(child->getColumnName(getContext()->getSettingsRef())); } } @@ -1243,7 +1243,7 @@ ActionsDAGPtr SelectQueryExpressionAnalyzer::appendOrderBy(ExpressionActionsChai if (!ast || ast->children.empty()) throw Exception("Bad order expression AST", ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE); ASTPtr order_expression = ast->children.at(0); - step.addRequiredOutput(order_expression->getColumnName()); + step.addRequiredOutput(order_expression->getColumnName(getContext()->getSettingsRef())); if (ast->with_fill) with_fill = true; @@ -1293,7 +1293,7 @@ bool SelectQueryExpressionAnalyzer::appendLimitBy(ExpressionActionsChain & chain for (const auto & child : select_query->limitBy()->children) { - auto child_name = child->getColumnName(); + auto child_name = child->getColumnName(getContext()->getSettingsRef()); if (!aggregated_names.count(child_name)) step.addRequiredOutput(std::move(child_name)); } @@ -1309,13 +1309,15 @@ ActionsDAGPtr SelectQueryExpressionAnalyzer::appendProjectResult(ExpressionActio NamesWithAliases result_columns; + const auto & settings = getContext()->getSettingsRef(); + ASTs asts = select_query->select()->children; for (const auto & ast : asts) { - String result_name = ast->getAliasOrColumnName(); + String result_name = ast->getAliasOrColumnName(settings); if (required_result_columns.empty() || required_result_columns.count(result_name)) { - std::string source_name = ast->getColumnName(); + std::string source_name = ast->getColumnName(settings); /* * For temporary columns created by ExpressionAnalyzer for literals, @@ -1357,7 +1359,7 @@ void ExpressionAnalyzer::appendExpression(ExpressionActionsChain & chain, const { ExpressionActionsChain::Step & step = chain.lastStep(sourceColumns()); getRootActions(expr, only_types, step.actions()); - step.addRequiredOutput(expr->getColumnName()); + step.addRequiredOutput(expr->getColumnName(getContext()->getSettingsRef())); } @@ -1374,12 +1376,13 @@ ActionsDAGPtr ExpressionAnalyzer::getActionsDAG(bool add_aliases, bool project_r else asts = ASTs(1, query); + const auto & settings = getContext()->getSettingsRef(); for (const auto & ast : asts) { - std::string name = ast->getColumnName(); + std::string name = ast->getColumnName(settings); std::string alias; if (add_aliases) - alias = ast->getAliasOrColumnName(); + alias = ast->getAliasOrColumnName(settings); else alias = name; result_columns.emplace_back(name, alias); @@ -1514,7 +1517,7 @@ ExpressionAnalysisResult::ExpressionAnalysisResult( if (auto actions = query_analyzer.appendPrewhere(chain, !first_stage, additional_required_columns_after_prewhere)) { - prewhere_info = std::make_shared(actions, query.prewhere()->getColumnName()); + prewhere_info = std::make_shared(actions, query.prewhere()->getColumnName(settings)); if (allowEarlyConstantFolding(*prewhere_info->prewhere_actions, settings)) { @@ -1524,7 +1527,7 @@ ExpressionAnalysisResult::ExpressionAnalysisResult( ExpressionActions( prewhere_info->prewhere_actions, ExpressionActionsSettings::fromSettings(context->getSettingsRef())).execute(before_prewhere_sample); - auto & column_elem = before_prewhere_sample.getByName(query.prewhere()->getColumnName()); + auto & column_elem = before_prewhere_sample.getByName(query.prewhere()->getColumnName(settings)); /// If the filter column is a constant, record it. if (column_elem.column) prewhere_constant_filter_description = ConstantFilterDescription(*column_elem.column); @@ -1559,7 +1562,7 @@ ExpressionAnalysisResult::ExpressionAnalysisResult( ExpressionActions( before_where, ExpressionActionsSettings::fromSettings(context->getSettingsRef())).execute(before_where_sample); - auto & column_elem = before_where_sample.getByName(query.where()->getColumnName()); + auto & column_elem = before_where_sample.getByName(query.where()->getColumnName(settings)); /// If the filter column is a constant, record it. if (column_elem.column) where_constant_filter_description = ConstantFilterDescription(*column_elem.column); @@ -1650,7 +1653,7 @@ ExpressionAnalysisResult::ExpressionAnalysisResult( const auto * select_query = query_analyzer.getSelectQuery(); for (const auto & child : select_query->select()->children) { - step.addRequiredOutput(child->getColumnName()); + step.addRequiredOutput(child->getColumnName(settings)); } } @@ -1706,7 +1709,8 @@ void ExpressionAnalysisResult::finalize(const ExpressionActionsChain & chain, si if (hasWhere()) { - where_column_name = query.where()->getColumnName(); + const auto & settings = chain.getContext()->getSettingsRef(); + where_column_name = query.where()->getColumnName(settings); remove_where_filter = chain.steps.at(where_step_num)->required_output.find(where_column_name)->second; } } diff --git a/src/Interpreters/InterpreterSelectQuery.cpp b/src/Interpreters/InterpreterSelectQuery.cpp index 85b9026c642..1b68628a7b2 100644 --- a/src/Interpreters/InterpreterSelectQuery.cpp +++ b/src/Interpreters/InterpreterSelectQuery.cpp @@ -142,7 +142,7 @@ String InterpreterSelectQuery::generateFilterActions(ActionsDAGPtr & actions, co SelectQueryExpressionAnalyzer analyzer(query_ast, syntax_result, context, metadata_snapshot); actions = analyzer.simpleSelectActions(); - auto column_name = expr_list->children.at(0)->getColumnName(); + auto column_name = expr_list->children.at(0)->getColumnName(context->getSettingsRef()); actions->removeUnusedActions(NameSet{column_name}); actions->projectInput(false); @@ -778,7 +778,7 @@ static SortDescription getSortDescription(const ASTSelectQuery & query, ContextP order_descr.reserve(query.orderBy()->children.size()); for (const auto & elem : query.orderBy()->children) { - String name = elem->children.front()->getColumnName(); + String name = elem->children.front()->getColumnName(context->getSettingsRef()); const auto & order_by_elem = elem->as(); std::shared_ptr collator; @@ -797,14 +797,14 @@ static SortDescription getSortDescription(const ASTSelectQuery & query, ContextP return order_descr; } -static SortDescription getSortDescriptionFromGroupBy(const ASTSelectQuery & query) +static SortDescription getSortDescriptionFromGroupBy(const ASTSelectQuery & query, ContextPtr context) { SortDescription order_descr; order_descr.reserve(query.groupBy()->children.size()); for (const auto & elem : query.groupBy()->children) { - String name = elem->getColumnName(); + String name = elem->getColumnName(context->getSettingsRef()); order_descr.emplace_back(name, 1, 1); } @@ -1945,13 +1945,13 @@ void InterpreterSelectQuery::executeFetchColumns(QueryProcessingStage::Enum proc { query_info.projection->order_optimizer = std::make_shared( query_info.projection->group_by_elements_actions, - getSortDescriptionFromGroupBy(query), + getSortDescriptionFromGroupBy(query, context), query_info.syntax_analyzer_result); } else { query_info.order_optimizer = std::make_shared( - analysis_result.group_by_elements_actions, getSortDescriptionFromGroupBy(query), query_info.syntax_analyzer_result); + analysis_result.group_by_elements_actions, getSortDescriptionFromGroupBy(query, context), query_info.syntax_analyzer_result); } } @@ -2030,7 +2030,7 @@ void InterpreterSelectQuery::executeFetchColumns(QueryProcessingStage::Enum proc void InterpreterSelectQuery::executeWhere(QueryPlan & query_plan, const ActionsDAGPtr & expression, bool remove_filter) { auto where_step = std::make_unique( - query_plan.getCurrentDataStream(), expression, getSelectQuery().where()->getColumnName(), remove_filter); + query_plan.getCurrentDataStream(), expression, getSelectQuery().where()->getColumnName(context->getSettingsRef()), remove_filter); where_step->setStepDescription("WHERE"); query_plan.addStep(std::move(where_step)); @@ -2077,7 +2077,7 @@ void InterpreterSelectQuery::executeAggregation(QueryPlan & query_plan, const Ac SortDescription group_by_sort_description; if (group_by_info && settings.optimize_aggregation_in_order) - group_by_sort_description = getSortDescriptionFromGroupBy(getSelectQuery()); + group_by_sort_description = getSortDescriptionFromGroupBy(getSelectQuery(), context); else group_by_info = nullptr; @@ -2125,7 +2125,7 @@ void InterpreterSelectQuery::executeMergeAggregated(QueryPlan & query_plan, bool void InterpreterSelectQuery::executeHaving(QueryPlan & query_plan, const ActionsDAGPtr & expression) { auto having_step - = std::make_unique(query_plan.getCurrentDataStream(), expression, getSelectQuery().having()->getColumnName(), false); + = std::make_unique(query_plan.getCurrentDataStream(), expression, getSelectQuery().having()->getColumnName(context->getSettingsRef()), false); having_step->setStepDescription("HAVING"); query_plan.addStep(std::move(having_step)); @@ -2141,7 +2141,7 @@ void InterpreterSelectQuery::executeTotalsAndHaving( query_plan.getCurrentDataStream(), overflow_row, expression, - has_having ? getSelectQuery().having()->getColumnName() : "", + has_having ? getSelectQuery().having()->getColumnName(context->getSettingsRef()) : "", settings.totals_mode, settings.totals_auto_threshold, final); @@ -2458,7 +2458,7 @@ void InterpreterSelectQuery::executeLimitBy(QueryPlan & query_plan) Names columns; for (const auto & elem : query.limitBy()->children) - columns.emplace_back(elem->getColumnName()); + columns.emplace_back(elem->getColumnName(context->getSettingsRef())); UInt64 length = getLimitUIntValue(query.limitByLength(), context, "LIMIT"); UInt64 offset = (query.limitByOffset() ? getLimitUIntValue(query.limitByOffset(), context, "OFFSET") : 0); diff --git a/src/Interpreters/evaluateConstantExpression.cpp b/src/Interpreters/evaluateConstantExpression.cpp index 2525f9672ed..90f6ac84afc 100644 --- a/src/Interpreters/evaluateConstantExpression.cpp +++ b/src/Interpreters/evaluateConstantExpression.cpp @@ -39,7 +39,7 @@ std::pair> evaluateConstantExpression(co if (context->getSettingsRef().normalize_function_names) FunctionNameNormalizer().visit(ast.get()); - String name = ast->getColumnName(); + String name = ast->getColumnName(context->getSettingsRef()); auto syntax_result = TreeRewriter(context).analyze(ast, source_columns); ExpressionActionsPtr expr_for_constant_folding = ExpressionAnalyzer(ast, syntax_result, context).getConstActions(); diff --git a/src/Parsers/ASTFunction.cpp b/src/Parsers/ASTFunction.cpp index cc460f600dd..5a666310083 100644 --- a/src/Parsers/ASTFunction.cpp +++ b/src/Parsers/ASTFunction.cpp @@ -22,6 +22,16 @@ namespace ErrorCodes } void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const +{ + appendColumnNameImpl(ostr, nullptr); +} + +void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr, const Settings & settings) const +{ + appendColumnNameImpl(ostr, &settings); +} + +void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr, const Settings * settings) const { if (name == "view") throw Exception("Table function view cannot be used as an expression", ErrorCodes::UNEXPECTED_EXPRESSION); @@ -35,19 +45,30 @@ void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const { if (it != parameters->children.begin()) writeCString(", ", ostr); - (*it)->appendColumnName(ostr); + + if (settings) + (*it)->appendColumnName(ostr, *settings); + else + (*it)->appendColumnName(ostr); } writeChar(')', ostr); } writeChar('(', ostr); if (arguments) + { for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it) { if (it != arguments->children.begin()) writeCString(", ", ostr); - (*it)->appendColumnName(ostr); + + if (settings) + (*it)->appendColumnName(ostr, *settings); + else + (*it)->appendColumnName(ostr); } + } + writeChar(')', ostr); if (is_window_function) @@ -59,11 +80,11 @@ void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const } else { - FormatSettings settings{ostr, true /* one_line */}; + FormatSettings format_settings{ostr, true /* one_line */}; FormatState state; FormatStateStacked frame; writeCString("(", ostr); - window_definition->formatImpl(settings, state, frame); + window_definition->formatImpl(format_settings, state, frame); writeCString(")", ostr); } } diff --git a/src/Parsers/ASTFunction.h b/src/Parsers/ASTFunction.h index 685aaaadd26..8e657afbf6e 100644 --- a/src/Parsers/ASTFunction.h +++ b/src/Parsers/ASTFunction.h @@ -54,6 +54,10 @@ public: protected: void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override; void appendColumnNameImpl(WriteBuffer & ostr) const override; + void appendColumnNameImpl(WriteBuffer & ostr, const Settings & settings) const override; + +private: + void appendColumnNameImpl(WriteBuffer & ostr, const Settings * settings) const; }; diff --git a/src/Parsers/ASTLiteral.cpp b/src/Parsers/ASTLiteral.cpp index ed6790499fb..ddad6b45e8d 100644 --- a/src/Parsers/ASTLiteral.cpp +++ b/src/Parsers/ASTLiteral.cpp @@ -16,8 +16,10 @@ void ASTLiteral::updateTreeHashImpl(SipHash & hash_state) const applyVisitor(FieldVisitorHash(hash_state), value); } +namespace +{ + /// Writes 'tuple' word before tuple literals for backward compatibility reasons. -/// TODO: remove, when versions lower than 20.3 will be rarely used. class FieldVisitorToColumnName : public StaticVisitor { public: @@ -45,14 +47,51 @@ String FieldVisitorToColumnName::operator() (const Tuple & x) const return wb.str(); } +} + +void ASTLiteral::appendColumnNameImpl(WriteBuffer & ostr, const Settings & settings) const +{ + if (settings.legacy_column_name_of_tuple_literal) + appendColumnNameImplLegacy(ostr); + else + appendColumnNameImpl(ostr); +} + void ASTLiteral::appendColumnNameImpl(WriteBuffer & ostr) const { /// 100 - just arbitrary value. constexpr auto min_elements_for_hashing = 100; + /// Special case for very large arrays and tuples. 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.) + auto type = value.getType(); + if ((type == Field::Types::Array && value.get().size() > min_elements_for_hashing) + || (type == Field::Types::Tuple && value.get().size() > min_elements_for_hashing)) + { + SipHash hash; + applyVisitor(FieldVisitorHash(hash), value); + UInt64 low, high; + hash.get128(low, high); + + writeCString(type == Field::Types::Array ? "__array_" : "__tuple_", ostr); + writeText(low, ostr); + ostr.write('_'); + writeText(high, ostr); + } + else + { + String column_name = applyVisitor(FieldVisitorToString(), value); + writeString(column_name, ostr); + } +} + +void ASTLiteral::appendColumnNameImplLegacy(WriteBuffer & ostr) const +{ + /// 100 - just arbitrary value. + constexpr auto min_elements_for_hashing = 100; + /// 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.) - /// TODO: Also do hashing for large tuples, when versions lower than 20.3 will be rarely used, because it breaks backward compatibility. auto type = value.getType(); if ((type == Field::Types::Array && value.get().size() > min_elements_for_hashing)) { diff --git a/src/Parsers/ASTLiteral.h b/src/Parsers/ASTLiteral.h index 7e472a16bdd..5292ab3c6c0 100644 --- a/src/Parsers/ASTLiteral.h +++ b/src/Parsers/ASTLiteral.h @@ -44,6 +44,13 @@ protected: void formatImplWithoutAlias(const FormatSettings & settings, FormatState &, FormatStateStacked) const override; void appendColumnNameImpl(WriteBuffer & ostr) const override; + void appendColumnNameImpl(WriteBuffer & ostr, const Settings & settings) const override; + +private: + /// Legacy version of 'appendColumnNameImpl'. It differs only with tuple literals. + /// It's only needed to continue working of queries with tuple literals + /// in distributed tables while rolling update. + void appendColumnNameImplLegacy(WriteBuffer & ostr) const; }; } diff --git a/src/Parsers/ASTWithAlias.cpp b/src/Parsers/ASTWithAlias.cpp index 88f6568a719..0f5b86763e0 100644 --- a/src/Parsers/ASTWithAlias.cpp +++ b/src/Parsers/ASTWithAlias.cpp @@ -48,6 +48,14 @@ void ASTWithAlias::appendColumnName(WriteBuffer & ostr) const appendColumnNameImpl(ostr); } +void ASTWithAlias::appendColumnName(WriteBuffer & ostr, const Settings & settings) const +{ + if (prefer_alias_to_column_name && !alias.empty()) + writeString(alias, ostr); + else + appendColumnNameImpl(ostr, settings); +} + void ASTWithAlias::appendColumnNameWithoutAlias(WriteBuffer & ostr) const { appendColumnNameImpl(ostr); diff --git a/src/Parsers/ASTWithAlias.h b/src/Parsers/ASTWithAlias.h index ea4419402b0..249be17b74c 100644 --- a/src/Parsers/ASTWithAlias.h +++ b/src/Parsers/ASTWithAlias.h @@ -21,8 +21,10 @@ public: using IAST::IAST; void appendColumnName(WriteBuffer & ostr) const final; + void appendColumnName(WriteBuffer & ostr, const Settings & settings) const final; void appendColumnNameWithoutAlias(WriteBuffer & ostr) const final; String getAliasOrColumnName() const override { return alias.empty() ? getColumnName() : alias; } + String getAliasOrColumnName(const Settings & settings) const override { return alias.empty() ? getColumnName(settings) : alias; } String tryGetAlias() const override { return alias; } void setAlias(const String & to) override { alias = to; } @@ -33,6 +35,7 @@ public: protected: virtual void appendColumnNameImpl(WriteBuffer & ostr) const = 0; + virtual void appendColumnNameImpl(WriteBuffer & ostr, const Settings &) const { appendColumnNameImpl(ostr); } }; /// helper for setting aliases and chaining result to other functions diff --git a/src/Parsers/IAST.cpp b/src/Parsers/IAST.cpp index 3a21d704eb9..0f38fcf98dd 100644 --- a/src/Parsers/IAST.cpp +++ b/src/Parsers/IAST.cpp @@ -109,6 +109,14 @@ String IAST::getColumnName() const } +String IAST::getColumnName(const Settings & settings) const +{ + WriteBufferFromOwnString write_buffer; + appendColumnName(write_buffer, settings); + return write_buffer.str(); +} + + String IAST::getColumnNameWithoutAlias() const { WriteBufferFromOwnString write_buffer; diff --git a/src/Parsers/IAST.h b/src/Parsers/IAST.h index 54e08b2700e..143094e1d7a 100644 --- a/src/Parsers/IAST.h +++ b/src/Parsers/IAST.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -41,13 +42,18 @@ public: /** Get the canonical name of the column if the element is a column */ String getColumnName() const; + String getColumnName(const Settings & settings) const; + /** Same as the above but ensure no alias names are used. This is for index analysis */ String getColumnNameWithoutAlias() const; + virtual void appendColumnName(WriteBuffer &) const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::LOGICAL_ERROR); } + virtual void appendColumnName(WriteBuffer & ostr, const Settings &) const { appendColumnName(ostr); } + virtual void appendColumnNameWithoutAlias(WriteBuffer &) const { throw Exception("Trying to get name of not a column: " + getID(), ErrorCodes::LOGICAL_ERROR); @@ -55,6 +61,7 @@ public: /** Get the alias, if any, or the canonical name of the column, if it is not. */ virtual String getAliasOrColumnName() const { return getColumnName(); } + virtual String getAliasOrColumnName(const Settings & settings) const { return getColumnName(settings); } /** Get the alias, if any, or an empty string if it does not exist, or if the element does not support aliases. */ virtual String tryGetAlias() const { return String(); } diff --git a/tests/integration/test_distributed_backward_compatability/configs/legacy.xml b/tests/integration/test_distributed_backward_compatability/configs/legacy.xml new file mode 100644 index 00000000000..01bd56de845 --- /dev/null +++ b/tests/integration/test_distributed_backward_compatability/configs/legacy.xml @@ -0,0 +1,7 @@ + + + + 1 + + + diff --git a/tests/integration/test_distributed_backward_compatability/test.py b/tests/integration/test_distributed_backward_compatability/test.py index eb18019c8df..0d36aaa23f4 100644 --- a/tests/integration/test_distributed_backward_compatability/test.py +++ b/tests/integration/test_distributed_backward_compatability/test.py @@ -5,8 +5,8 @@ from helpers.cluster import ClickHouseCluster cluster = ClickHouseCluster(__file__) node_old = cluster.add_instance('node1', main_configs=['configs/remote_servers.xml'], image='yandex/clickhouse-server', - tag='19.17.8.54', stay_alive=True, with_installed_binary=True) -node_new = cluster.add_instance('node2', main_configs=['configs/remote_servers.xml']) + tag='20.8.9.6', stay_alive=True, with_installed_binary=True) +node_new = cluster.add_instance('node2', main_configs=['configs/remote_servers.xml'], user_configs=['configs/legacy.xml']) @pytest.fixture(scope="module") diff --git a/tests/queries/0_stateless/01913_names_of_tuple_literal.reference b/tests/queries/0_stateless/01913_names_of_tuple_literal.reference new file mode 100644 index 00000000000..a4c05ad853a --- /dev/null +++ b/tests/queries/0_stateless/01913_names_of_tuple_literal.reference @@ -0,0 +1,4 @@ +((1, 2), (2, 3), (3, 4)) +((1,2),(2,3),(3,4)) +tuple(tuple(1, 2), tuple(2, 3), tuple(3, 4)) +((1,2),(2,3),(3,4)) diff --git a/tests/queries/0_stateless/01913_names_of_tuple_literal.sql b/tests/queries/0_stateless/01913_names_of_tuple_literal.sql new file mode 100644 index 00000000000..09de9e8cf37 --- /dev/null +++ b/tests/queries/0_stateless/01913_names_of_tuple_literal.sql @@ -0,0 +1,2 @@ +SELECT ((1, 2), (2, 3), (3, 4)) FORMAT TSVWithNames; +SELECT ((1, 2), (2, 3), (3, 4)) FORMAT TSVWithNames SETTINGS legacy_column_name_of_tuple_literal = 1;