mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-17 21:24:28 +00:00
Fix GLOBAL IN evaluation
This commit is contained in:
parent
9250d5c4e9
commit
d69b6307b5
@ -526,6 +526,7 @@ bool ActionsMatcher::needChildVisit(const ASTPtr & node, const ASTPtr & child)
|
|||||||
{
|
{
|
||||||
/// Visit children themself
|
/// Visit children themself
|
||||||
if (node->as<ASTIdentifier>() ||
|
if (node->as<ASTIdentifier>() ||
|
||||||
|
node->as<ASTTableIdentifier>() ||
|
||||||
node->as<ASTFunction>() ||
|
node->as<ASTFunction>() ||
|
||||||
node->as<ASTLiteral>() ||
|
node->as<ASTLiteral>() ||
|
||||||
node->as<ASTExpressionList>())
|
node->as<ASTExpressionList>())
|
||||||
@ -543,6 +544,8 @@ void ActionsMatcher::visit(const ASTPtr & ast, Data & data)
|
|||||||
{
|
{
|
||||||
if (const auto * identifier = ast->as<ASTIdentifier>())
|
if (const auto * identifier = ast->as<ASTIdentifier>())
|
||||||
visit(*identifier, ast, data);
|
visit(*identifier, ast, data);
|
||||||
|
else if (const auto * table = ast->as<ASTTableIdentifier>())
|
||||||
|
visit(*table, ast, data);
|
||||||
else if (const auto * node = ast->as<ASTFunction>())
|
else if (const auto * node = ast->as<ASTFunction>())
|
||||||
visit(*node, ast, data);
|
visit(*node, ast, data);
|
||||||
else if (const auto * literal = ast->as<ASTLiteral>())
|
else if (const auto * literal = ast->as<ASTLiteral>())
|
||||||
@ -659,9 +662,9 @@ void ActionsMatcher::visit(ASTExpressionList & expression_list, const ASTPtr &,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr & ast, Data & data)
|
void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr &, Data & data)
|
||||||
{
|
{
|
||||||
auto column_name = ast->getColumnName();
|
auto column_name = identifier.getColumnName();
|
||||||
if (data.hasColumn(column_name))
|
if (data.hasColumn(column_name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1004,7 +1007,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data, bool no_su
|
|||||||
const ASTPtr & right_in_operand = args.children.at(1);
|
const ASTPtr & right_in_operand = args.children.at(1);
|
||||||
|
|
||||||
/// If the subquery or table name for SELECT.
|
/// If the subquery or table name for SELECT.
|
||||||
const auto * identifier = right_in_operand->as<ASTIdentifier>();
|
const auto * identifier = right_in_operand->as<ASTTableIdentifier>();
|
||||||
if (right_in_operand->as<ASTSubquery>() || identifier)
|
if (right_in_operand->as<ASTSubquery>() || identifier)
|
||||||
{
|
{
|
||||||
if (no_subqueries)
|
if (no_subqueries)
|
||||||
|
@ -158,9 +158,7 @@ public:
|
|||||||
static bool needChildVisit(ASTPtr &, const ASTPtr & child)
|
static bool needChildVisit(ASTPtr &, const ASTPtr & child)
|
||||||
{
|
{
|
||||||
/// We do not go into subqueries.
|
/// We do not go into subqueries.
|
||||||
if (child->as<ASTSelectQuery>())
|
return !child->as<ASTSelectQuery>();
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <Poco/String.h>
|
#include <Poco/String.h>
|
||||||
|
#include <IO/WriteBufferFromOStream.h>
|
||||||
#include <Interpreters/misc.h>
|
#include <Interpreters/misc.h>
|
||||||
#include <Interpreters/MarkTableIdentifiersVisitor.h>
|
#include <Interpreters/MarkTableIdentifiersVisitor.h>
|
||||||
#include <Interpreters/IdentifierSemantic.h>
|
#include <Interpreters/IdentifierSemantic.h>
|
||||||
@ -24,29 +25,35 @@ void MarkTableIdentifiersMatcher::visit(ASTPtr & ast, Data & data)
|
|||||||
visit(*node_func, ast, data);
|
visit(*node_func, ast, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr &, Data & data)
|
void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr & ptr, Data & data)
|
||||||
{
|
{
|
||||||
/// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`.
|
/// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`.
|
||||||
if (checkFunctionIsInOrGlobalInOperator(func))
|
if (checkFunctionIsInOrGlobalInOperator(func))
|
||||||
{
|
{
|
||||||
auto & ast = func.arguments->children.at(1);
|
auto ast = func.arguments->children.at(1);
|
||||||
auto opt_name = tryGetIdentifierName(ast);
|
auto opt_name = tryGetIdentifierName(ast);
|
||||||
if (opt_name && !data.aliases.count(*opt_name))
|
if (opt_name && !data.aliases.count(*opt_name))
|
||||||
setIdentifierSpecial(ast);
|
{
|
||||||
|
ptr = func.clone();
|
||||||
|
ptr->as<ASTFunction>()->arguments->children[1] = ast->as<ASTIdentifier>()->createTable();
|
||||||
|
assert(ptr->as<ASTFunction>()->arguments->children[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First argument of joinGet can be a table name, perhaps with a database.
|
// First argument of joinGet can be a table name, perhaps with a database.
|
||||||
// First argument of dictGet can be a dictionary name, perhaps with a database.
|
// First argument of dictGet can be a dictionary name, perhaps with a database.
|
||||||
if (functionIsJoinGet(func.name) || functionIsDictGet(func.name))
|
else if (functionIsJoinGet(func.name) || functionIsDictGet(func.name))
|
||||||
{
|
{
|
||||||
if (func.arguments->children.empty())
|
if (func.arguments->children.empty())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
auto & ast = func.arguments->children.at(0);
|
auto & ast = func.arguments->children.at(0);
|
||||||
auto opt_name = tryGetIdentifierName(ast);
|
auto opt_name = tryGetIdentifierName(ast);
|
||||||
if (opt_name && !data.aliases.count(*opt_name))
|
if (opt_name && !data.aliases.count(*opt_name))
|
||||||
setIdentifierSpecial(ast);
|
{
|
||||||
|
ptr = func.clone();
|
||||||
|
ptr->as<ASTFunction>()->arguments->children[0] = ast->as<ASTIdentifier>()->createTable();
|
||||||
|
assert(ptr->as<ASTFunction>()->arguments->children[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,13 @@ void ASTIdentifier::restoreTable()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ASTTableIdentifier> ASTIdentifier::createTable() const
|
||||||
|
{
|
||||||
|
if (name_parts.size() == 1) return std::make_shared<ASTTableIdentifier>(name_parts[0]);
|
||||||
|
if (name_parts.size() == 2) return std::make_shared<ASTTableIdentifier>(name_parts[0], name_parts[1]);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ASTIdentifier::resetFullName()
|
void ASTIdentifier::resetFullName()
|
||||||
{
|
{
|
||||||
full_name = name_parts[0];
|
full_name = name_parts[0];
|
||||||
|
@ -14,10 +14,11 @@ struct IdentifierSemantic;
|
|||||||
struct IdentifierSemanticImpl;
|
struct IdentifierSemanticImpl;
|
||||||
struct StorageID;
|
struct StorageID;
|
||||||
|
|
||||||
|
class ASTTableIdentifier;
|
||||||
|
|
||||||
/// Generic identifier. ASTTableIdentifier - for table identifier.
|
/// Generic identifier. ASTTableIdentifier - for table identifier.
|
||||||
class ASTIdentifier : public ASTWithAlias
|
class ASTIdentifier : public ASTWithAlias
|
||||||
{
|
{
|
||||||
friend class ReplaceQueryParameterVisitor;
|
|
||||||
public:
|
public:
|
||||||
explicit ASTIdentifier(const String & short_name, ASTPtr && name_param = {});
|
explicit ASTIdentifier(const String & short_name, ASTPtr && name_param = {});
|
||||||
explicit ASTIdentifier(std::vector<String> && name_parts, bool special = false, std::vector<ASTPtr> && name_params = {});
|
explicit ASTIdentifier(std::vector<String> && name_parts, bool special = false, std::vector<ASTPtr> && name_params = {});
|
||||||
@ -44,6 +45,7 @@ public:
|
|||||||
const String & name() const;
|
const String & name() const;
|
||||||
|
|
||||||
void restoreTable(); // TODO(ilezhankin): get rid of this
|
void restoreTable(); // TODO(ilezhankin): get rid of this
|
||||||
|
std::shared_ptr<ASTTableIdentifier> createTable() const; // return |nullptr| if identifier is not table.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String full_name;
|
String full_name;
|
||||||
@ -56,10 +58,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
using ASTWithAlias::children; /// ASTIdentifier is child free
|
using ASTWithAlias::children; /// ASTIdentifier is child free
|
||||||
|
|
||||||
|
friend class ReplaceQueryParameterVisitor;
|
||||||
friend struct IdentifierSemantic;
|
friend struct IdentifierSemantic;
|
||||||
friend ASTPtr createTableIdentifier(const StorageID & table_id);
|
|
||||||
friend void setIdentifierSpecial(ASTPtr & ast);
|
friend void setIdentifierSpecial(ASTPtr & ast);
|
||||||
friend StorageID getTableIdentifier(const ASTPtr & ast);
|
|
||||||
|
|
||||||
void resetFullName();
|
void resetFullName();
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python3.8
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import collections
|
import collections
|
||||||
|
Loading…
Reference in New Issue
Block a user