1515#include < Interpreters/Cluster.h>
1616#include < Interpreters/DatabaseCatalog.h>
1717#include < Interpreters/AddDefaultDatabaseVisitor.h>
18+ #include < Interpreters/addTypeConversionToAST.h>
1819#include < Interpreters/RequiredSourceColumnsVisitor.h>
1920#include < Interpreters/TranslateQualifiedNamesVisitor.h>
2021#include < DataTypes/ObjectUtils.h>
2122#include < Client/IConnections.h>
2223#include < Parsers/ASTSelectQuery.h>
2324#include < Parsers/ASTSetQuery.h>
25+ #include < Parsers/ASTIdentifier.h>
2426#include < Processors/QueryPlan/QueryPlan.h>
2527#include < Processors/QueryPlan/ReadFromRemote.h>
2628#include < Processors/QueryPlan/ExpressionStep.h>
@@ -60,6 +62,46 @@ namespace FailPoints
6062namespace ClusterProxy
6163{
6264
65+ namespace
66+ {
67+ void applyHybridCastsToAST (
68+ ASTPtr & node,
69+ const ColumnsDescription * metadata_columns,
70+ const NameSet * columns_to_cast)
71+ {
72+ if (!metadata_columns || !columns_to_cast || columns_to_cast->empty () || !node)
73+ return ;
74+
75+ if (auto * func = node->as <ASTFunction>(); func && func->name == " _CAST" )
76+ return ;
77+
78+ if (auto * identifier = node->as <ASTIdentifier>())
79+ {
80+ String candidate = identifier->name ();
81+ String short_name = candidate;
82+
83+ auto dot_pos = candidate.rfind (' .' );
84+ if (dot_pos != String::npos && dot_pos + 1 < candidate.size ())
85+ short_name = candidate.substr (dot_pos + 1 );
86+
87+ if (columns_to_cast->contains (short_name))
88+ {
89+ if (auto expected_column_opt = metadata_columns->tryGetPhysical (short_name))
90+ {
91+ auto cast_ast = addTypeConversionToAST (node->clone (), expected_column_opt->type ->getName ());
92+ const auto & alias = identifier->alias .empty () ? short_name : identifier->alias ;
93+ cast_ast->setAlias (alias);
94+ node = cast_ast;
95+ return ;
96+ }
97+ }
98+ }
99+
100+ for (auto & child : node->children )
101+ applyHybridCastsToAST (child, metadata_columns, columns_to_cast);
102+ }
103+ }
104+
63105// / select query has database, table and table function names as AST pointers
64106// / Creates a copy of query, changes database, table and table function names.
65107ASTPtr rewriteSelectQuery (
@@ -68,7 +110,9 @@ ASTPtr rewriteSelectQuery(
68110 const std::string & remote_database,
69111 const std::string & remote_table,
70112 ASTPtr table_function_ptr,
71- ASTPtr additional_filter)
113+ ASTPtr additional_filter,
114+ const NameSet * columns_to_cast,
115+ const ColumnsDescription * metadata_columns)
72116{
73117 auto modified_query_ast = query->clone ();
74118
@@ -122,6 +166,9 @@ ASTPtr rewriteSelectQuery(
122166
123167 RestoreQualifiedNamesVisitor (data).visit (modified_query_ast);
124168 }
169+
170+ if (columns_to_cast && !columns_to_cast->empty () && metadata_columns)
171+ applyHybridCastsToAST (modified_query_ast, metadata_columns, columns_to_cast);
125172 }
126173
127174 // / To make local JOIN works, default database should be added to table names.
0 commit comments