| 238 | } |
| 239 | |
| 240 | bool QueryUseOptimizerVisitor::visitASTSelectQuery(ASTPtr & node, QueryUseOptimizerContext & context) |
| 241 | { |
| 242 | auto * select = node->as<ASTSelectQuery>(); |
| 243 | |
| 244 | if (select->limit_with_ties) |
| 245 | { |
| 246 | reason = "LIMIT/OFFSET FETCH WITH TIES not implemented"; |
| 247 | return false; |
| 248 | } |
| 249 | |
| 250 | if (context.disallow_subquery) |
| 251 | { |
| 252 | reason = "nullIn/globalNullIn/notNullIn/globalNotNullIn function with subquery not implemented"; |
| 253 | return false; |
| 254 | } |
| 255 | |
| 256 | if (select->group_by_with_totals && context.disallow_with_totals) |
| 257 | { |
| 258 | reason = "group by with totals only supports with totals at outmost select"; |
| 259 | return false; |
| 260 | } |
| 261 | auto has_join = [](const auto & sel_query) { return sel_query.tables() && sel_query.tables()->children.size() > 1; }; |
| 262 | |
| 263 | QueryUseOptimizerContext child_context{.context = context.context, .ctes = context.ctes, .disallow_with_totals = has_join(*select)}; |
| 264 | collectWithTableNames(*select, child_context.ctes); |
| 265 | |
| 266 | for (const auto * table_expression : getTableExpressions(*select)) |
| 267 | { |
| 268 | if (!checkDatabaseAndTable(*table_expression, child_context.context, child_context.ctes)) |
| 269 | { |
| 270 | reason = "unsupported storage: " + table_expression->formatForErrorMessage(); |
| 271 | return false; |
| 272 | } |
| 273 | if (table_expression->table_function) |
| 274 | { |
| 275 | const auto & function = table_expression->table_function->as<ASTFunction &>(); |
| 276 | |
| 277 | if (function.name == "fusionMerge") |
| 278 | return true; |
| 279 | |
| 280 | reason = "table function"; |
| 281 | return false; |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | return visitNode(node, child_context); |
| 286 | } |
| 287 | |
| 288 | bool QueryUseOptimizerVisitor::visitASTTableJoin(ASTPtr & node, QueryUseOptimizerContext & context) |
| 289 | { |
nothing calls this directly
no test coverage detected