mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Shadow lambda arguments
In case of ambiguity, lambda functions should prefer its arguments to other aliases or identifiers
This commit is contained in:
parent
4f0dbae0f9
commit
8b9778ebb6
@ -3,6 +3,7 @@
|
|||||||
#include <Interpreters/QueryNormalizer.h>
|
#include <Interpreters/QueryNormalizer.h>
|
||||||
#include <Interpreters/IdentifierSemantic.h>
|
#include <Interpreters/IdentifierSemantic.h>
|
||||||
#include <Interpreters/Context.h>
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Interpreters/RequiredSourceColumnsVisitor.h>
|
||||||
#include <Parsers/ASTFunction.h>
|
#include <Parsers/ASTFunction.h>
|
||||||
#include <Parsers/ASTIdentifier.h>
|
#include <Parsers/ASTIdentifier.h>
|
||||||
#include <Parsers/ASTSelectQuery.h>
|
#include <Parsers/ASTSelectQuery.h>
|
||||||
@ -170,6 +171,24 @@ void QueryNormalizer::visitChildren(IAST * node, Data & data)
|
|||||||
/// Don't go into query argument.
|
/// Don't go into query argument.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For lambda functions we need to avoid replacing lambda parameters with external aliases, for example,
|
||||||
|
/// Select 1 as x, arrayMap(x -> x + 2, [1, 2, 3])
|
||||||
|
/// shouldn't be replaced with Select 1 as x, arrayMap(x -> **(1 as x)** + 2, [1, 2, 3])
|
||||||
|
Aliases extracted_aliases;
|
||||||
|
if (func_node->name == "lambda")
|
||||||
|
{
|
||||||
|
Names lambda_aliases = RequiredSourceColumnsMatcher::extractNamesFromLambda(*func_node);
|
||||||
|
for (const auto & name : lambda_aliases)
|
||||||
|
{
|
||||||
|
auto it = data.aliases.find(name);
|
||||||
|
if (it != data.aliases.end())
|
||||||
|
{
|
||||||
|
extracted_aliases.insert(data.aliases.extract(it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// We skip the first argument. We also assume that the lambda function can not have parameters.
|
/// We skip the first argument. We also assume that the lambda function can not have parameters.
|
||||||
size_t first_pos = 0;
|
size_t first_pos = 0;
|
||||||
if (func_node->name == "lambda")
|
if (func_node->name == "lambda")
|
||||||
@ -192,6 +211,11 @@ void QueryNormalizer::visitChildren(IAST * node, Data & data)
|
|||||||
{
|
{
|
||||||
visitChildren(func_node->window_definition.get(), data);
|
visitChildren(func_node->window_definition.get(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto & it : extracted_aliases)
|
||||||
|
{
|
||||||
|
data.aliases.insert(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!node->as<ASTSelectQuery>())
|
else if (!node->as<ASTSelectQuery>())
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
using SetOfASTs = std::set<const IAST *>;
|
using SetOfASTs = std::set<const IAST *>;
|
||||||
using MapOfASTs = std::map<ASTPtr, ASTPtr>;
|
using MapOfASTs = std::map<ASTPtr, ASTPtr>;
|
||||||
|
|
||||||
const Aliases & aliases;
|
Aliases & aliases;
|
||||||
const NameSet & source_columns_set;
|
const NameSet & source_columns_set;
|
||||||
ExtractedSettings settings;
|
ExtractedSettings settings;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
/// It's Ok to have "c + 1 AS c" in queries, but not in table definition
|
/// It's Ok to have "c + 1 AS c" in queries, but not in table definition
|
||||||
const bool allow_self_aliases; /// for constructs like "SELECT column + 1 AS column"
|
const bool allow_self_aliases; /// for constructs like "SELECT column + 1 AS column"
|
||||||
|
|
||||||
Data(const Aliases & aliases_, const NameSet & source_columns_set_, bool ignore_alias_, ExtractedSettings && settings_, bool allow_self_aliases_)
|
Data(Aliases & aliases_, const NameSet & source_columns_set_, bool ignore_alias_, ExtractedSettings && settings_, bool allow_self_aliases_)
|
||||||
: aliases(aliases_)
|
: aliases(aliases_)
|
||||||
, source_columns_set(source_columns_set_)
|
, source_columns_set(source_columns_set_)
|
||||||
, settings(settings_)
|
, settings(settings_)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
1000 [2,3,4]
|
||||||
|
1
|
||||||
|
1
|
25
tests/queries/0_stateless/01960_lambda_precedence.sql
Normal file
25
tests/queries/0_stateless/01960_lambda_precedence.sql
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
SELECT
|
||||||
|
1000 AS a,
|
||||||
|
arrayMap(a -> (a + 1), [1, 2, 3]);
|
||||||
|
|
||||||
|
|
||||||
|
-- https://github.com/ClickHouse/ClickHouse/issues/5046
|
||||||
|
SELECT sum(c1) AS v
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
1 AS c1,
|
||||||
|
['v'] AS c2
|
||||||
|
)
|
||||||
|
WHERE arrayExists(v -> (v = 'v'), c2);
|
||||||
|
|
||||||
|
|
||||||
|
SELECT sum(c1) AS v
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
1 AS c1,
|
||||||
|
['v'] AS c2,
|
||||||
|
['d'] AS d
|
||||||
|
)
|
||||||
|
WHERE arrayExists(i -> (d = ['d']), c2);
|
Loading…
Reference in New Issue
Block a user