3333#include < Analyzer/ColumnNode.h>
3434#include < Analyzer/JoinNode.h>
3535#include < Analyzer/InDepthQueryTreeVisitor.h>
36+ #include < Analyzer/Utils.h>
3637#include < Storages/StorageDistributed.h>
3738#include < TableFunctions/TableFunctionFactory.h>
3839
@@ -222,37 +223,40 @@ void IStorageCluster::updateQueryWithJoinToSendIfNeeded(
222223 {
223224 case ObjectStorageClusterJoinMode::LOCAL:
224225 {
225- auto modified_query_tree = query_tree->clone ();
226- bool need_modify = false ;
226+ if (has_join || has_local_columns_in_where)
227+ {
228+ auto modified_query_tree = query_tree->clone ();
227229
228- SearcherVisitor table_function_searcher ({QueryTreeNodeType::TABLE, QueryTreeNodeType::TABLE_FUNCTION}, context);
229- table_function_searcher.visit (query_tree );
230- auto table_function_node = table_function_searcher.getNode ();
231- if (!table_function_node)
232- throw Exception (ErrorCodes::LOGICAL_ERROR, " Can't find table function node" );
230+ SearcherVisitor table_function_searcher ({QueryTreeNodeType::TABLE, QueryTreeNodeType::TABLE_FUNCTION}, context);
231+ table_function_searcher.visit (modified_query_tree );
232+ auto table_function_node = table_function_searcher.getNode ();
233+ if (!table_function_node)
234+ throw Exception (ErrorCodes::LOGICAL_ERROR, " Can't find table function node" );
233235
234- if (has_join)
235- {
236236 QueryTreeNodePtr query_tree_distributed;
237237
238238 auto & query_node = modified_query_tree->as <QueryNode &>();
239239
240- if (table_function_searcher.getType ().value () == QueryTreeNodeType::TABLE_FUNCTION)
241- {
242- auto table_function = extractTableFunctionASTPtrFromSelectQuery (query_to_send);
243- query_tree_distributed = buildTableFunctionQueryTree (table_function, context);
244- auto & table_function_ast = table_function->as <ASTFunction &>();
245- query_tree_distributed->setAlias (table_function_ast.alias );
246- }
247- else
240+ if (has_join)
248241 {
249- auto join_node = query_node.getJoinTree ();
250- query_tree_distributed = join_node->as <JoinNode>()->getLeftTableExpression ()->clone ();
242+ if (table_function_searcher.getType ().value () == QueryTreeNodeType::TABLE_FUNCTION)
243+ {
244+ auto table_function = extractTableFunctionASTPtrFromSelectQuery (query_to_send);
245+ query_tree_distributed = buildTableFunctionQueryTree (table_function, context);
246+ auto & table_function_ast = table_function->as <ASTFunction &>();
247+ query_tree_distributed->setAlias (table_function_ast.alias );
248+ }
249+ else
250+ {
251+ auto join_node = query_node.getJoinTree ();
252+ query_tree_distributed = join_node->as <JoinNode>()->getLeftTableExpression ()->clone ();
253+ }
251254 }
252255
253256 // Find add used columns from table function to make proper projection list
257+ // Need to do before changing WHERE condition
254258 CollectUsedColumnsForSourceVisitor collector (table_function_node, context);
255- collector.visit (query_tree );
259+ collector.visit (modified_query_tree );
256260 const auto & columns = collector.getColumns ();
257261
258262 query_node.resolveProjectionColumns (columns);
@@ -262,20 +266,26 @@ void IStorageCluster::updateQueryWithJoinToSendIfNeeded(
262266 column_nodes_to_select->getNodes ().emplace_back (std::make_shared<ColumnNode>(column, table_function_node));
263267 query_node.getProjectionNode () = column_nodes_to_select;
264268
265- // Left only table function to send on cluster nodes
266- modified_query_tree = modified_query_tree->cloneAndReplace (query_node.getJoinTree (), query_tree_distributed);
269+ if (has_local_columns_in_where)
270+ {
271+ if (query_node.getPrewhere ())
272+ removeExpressionsThatDoNotDependOnTableIdentifiers (query_node.getPrewhere (), table_function_node, context);
273+ if (query_node.getWhere ())
274+ removeExpressionsThatDoNotDependOnTableIdentifiers (query_node.getWhere (), table_function_node, context);
275+ }
276+
277+ query_node.getOrderByNode () = std::make_shared<ListNode>();
278+ query_node.getGroupByNode () = std::make_shared<ListNode>();
267279
268- need_modify = true ;
269- }
280+ if (query_tree_distributed)
281+ {
282+ // Left only table function to send on cluster nodes
283+ modified_query_tree = modified_query_tree->cloneAndReplace (query_node.getJoinTree (), query_tree_distributed);
284+ }
270285
271- if (has_local_columns_in_where)
272- {
273- auto & query_node = modified_query_tree->as <QueryNode &>();
274- query_node.getWhere () = {};
286+ query_to_send = queryNodeToDistributedSelectQuery (modified_query_tree);
275287 }
276288
277- if (need_modify)
278- query_to_send = queryNodeToDistributedSelectQuery (modified_query_tree);
279289 return ;
280290 }
281291 case ObjectStorageClusterJoinMode::GLOBAL:
@@ -530,12 +540,16 @@ QueryProcessingStage::Enum IStorageCluster::getQueryProcessingStage(
530540 throw Exception (ErrorCodes::LOGICAL_ERROR, " Can't find table or table function node" );
531541
532542 auto & query_node = query_info.query_tree ->as <QueryNode &>();
533- if (query_node.hasWhere ())
543+ if (query_node.hasWhere () || query_node. hasPrewhere () )
534544 {
535545 CollectUsedColumnsForSourceVisitor collector_where (table_function_node, context, true );
536- collector_where.visit (query_node.getWhere ());
546+ if (query_node.hasPrewhere ())
547+ collector_where.visit (query_node.getPrewhere ());
548+ if (query_node.hasWhere ())
549+ collector_where.visit (query_node.getWhere ());
537550
538- // Can't use 'WHERE' on remote node if it contains columns from other sources
551+ // SELECT x FROM datalake.table WHERE x IN local.table
552+ // Need to modify 'WHERE' on remote node if it contains columns from other sources
539553 if (!collector_where.getColumns ().empty ())
540554 has_local_columns_in_where = true ;
541555 }
0 commit comments