mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #56380 from ClickHouse/vdimir/filter_pushdown_crash
Fix crash in filterPushDown
This commit is contained in:
commit
e8e3d4d310
@ -464,12 +464,19 @@ void ActionsDAG::removeUnusedActions(const Names & required_names, bool allow_re
|
||||
|
||||
void ActionsDAG::removeUnusedActions(bool allow_remove_inputs, bool allow_constant_folding)
|
||||
{
|
||||
std::unordered_set<const Node *> visited_nodes;
|
||||
std::unordered_set<const Node *> used_inputs;
|
||||
std::stack<Node *> stack;
|
||||
if (!allow_remove_inputs)
|
||||
{
|
||||
for (const auto * input : inputs)
|
||||
used_inputs.insert(input);
|
||||
}
|
||||
removeUnusedActions(used_inputs, allow_constant_folding);
|
||||
}
|
||||
|
||||
for (const auto * input : inputs)
|
||||
used_inputs.insert(input);
|
||||
void ActionsDAG::removeUnusedActions(const std::unordered_set<const Node *> & used_inputs, bool allow_constant_folding)
|
||||
{
|
||||
std::unordered_set<const Node *> visited_nodes;
|
||||
std::stack<Node *> stack;
|
||||
|
||||
for (const auto * node : outputs)
|
||||
{
|
||||
@ -488,7 +495,7 @@ void ActionsDAG::removeUnusedActions(bool allow_remove_inputs, bool allow_consta
|
||||
stack.push(&node);
|
||||
}
|
||||
|
||||
if (node.type == ActionType::INPUT && !allow_remove_inputs && used_inputs.contains(&node))
|
||||
if (node.type == ActionType::INPUT && used_inputs.contains(&node))
|
||||
visited_nodes.insert(&node);
|
||||
}
|
||||
|
||||
@ -2187,14 +2194,6 @@ ActionsDAGPtr ActionsDAG::cloneActionsForFilterPushDown(
|
||||
{
|
||||
/// If filter column is not needed, remove it from output nodes.
|
||||
std::erase_if(outputs, [&](const Node * node) { return node == predicate; });
|
||||
|
||||
/// At the very end of this method we'll call removeUnusedActions() with allow_remove_inputs=false,
|
||||
/// so we need to manually remove predicate if it is an input node.
|
||||
if (predicate->type == ActionType::INPUT)
|
||||
{
|
||||
std::erase_if(inputs, [&](const Node * node) { return node == predicate; });
|
||||
nodes.remove_if([&](const Node & node) { return &node == predicate; });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2261,7 +2260,15 @@ ActionsDAGPtr ActionsDAG::cloneActionsForFilterPushDown(
|
||||
}
|
||||
}
|
||||
|
||||
removeUnusedActions(false);
|
||||
std::unordered_set<const Node *> used_inputs;
|
||||
for (const auto * input : inputs)
|
||||
{
|
||||
if (can_remove_filter && input == predicate)
|
||||
continue;
|
||||
used_inputs.insert(input);
|
||||
}
|
||||
|
||||
removeUnusedActions(used_inputs);
|
||||
return actions;
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,9 @@ public:
|
||||
/// Remove actions that are not needed to compute output nodes
|
||||
void removeUnusedActions(bool allow_remove_inputs = true, bool allow_constant_folding = true);
|
||||
|
||||
/// Remove actions that are not needed to compute output nodes. Keep inputs from used_inputs.
|
||||
void removeUnusedActions(const std::unordered_set<const Node *> & used_inputs, bool allow_constant_folding = true);
|
||||
|
||||
/// Remove actions that are not needed to compute output nodes with required names
|
||||
void removeUnusedActions(const Names & required_names, bool allow_remove_inputs = true, bool allow_constant_folding = true);
|
||||
|
||||
|
18
tests/queries/0_stateless/02907_filter_pushdown_crash.sql
Normal file
18
tests/queries/0_stateless/02907_filter_pushdown_crash.sql
Normal file
@ -0,0 +1,18 @@
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
|
||||
CREATE TABLE t1 (key UInt8) ENGINE = MergeTree ORDER BY key;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
CREATE TABLE t2 (key UInt32) ENGINE = MergeTree ORDER BY key;
|
||||
INSERT INTO t2 VALUES (1),(2);
|
||||
|
||||
SELECT a FROM ( SELECT key + 1 as a, key FROM t1 GROUP BY key ) WHERE key FORMAT Null;
|
||||
|
||||
SET join_algorithm = 'full_sorting_merge';
|
||||
SET max_rows_in_set_to_optimize_join = 0;
|
||||
|
||||
SELECT key FROM ( SELECT key FROM t1 GROUP BY key ) t1 JOIN (SELECT key FROM t2) t2 ON t1.key = t2.key WHERE key FORMAT Null;
|
||||
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
Loading…
Reference in New Issue
Block a user