| 1230 | } |
| 1231 | |
| 1232 | static std::shared_ptr<const ActionsDAG> getFilterFromQuery(const ASTPtr & ast, ContextPtr context) |
| 1233 | { |
| 1234 | QueryPlan plan; |
| 1235 | SelectQueryOptions options; |
| 1236 | options.only_analyze = true; |
| 1237 | if (context->getSettingsRef()[Setting::allow_experimental_analyzer]) |
| 1238 | { |
| 1239 | InterpreterSelectQueryAnalyzer interpreter(ast, context, options); |
| 1240 | plan = std::move(interpreter).extractQueryPlan(); |
| 1241 | } |
| 1242 | else |
| 1243 | { |
| 1244 | InterpreterSelectWithUnionQuery interpreter(ast, context, options); |
| 1245 | interpreter.buildQueryPlan(plan); |
| 1246 | } |
| 1247 | |
| 1248 | plan.optimize(QueryPlanOptimizationSettings(context)); |
| 1249 | |
| 1250 | std::stack<QueryPlan::Node *> nodes; |
| 1251 | nodes.push(plan.getRootNode()); |
| 1252 | |
| 1253 | SourceStepWithFilter * source = nullptr; |
| 1254 | |
| 1255 | while (!nodes.empty()) |
| 1256 | { |
| 1257 | const auto * node = nodes.top(); |
| 1258 | nodes.pop(); |
| 1259 | |
| 1260 | if (auto * with_filter = dynamic_cast<SourceStepWithFilter *>(node->step.get())) |
| 1261 | { |
| 1262 | if (source) |
| 1263 | { |
| 1264 | WriteBufferFromOwnString buf; |
| 1265 | plan.explainPlan(buf, {}); |
| 1266 | throw Exception(ErrorCodes::LOGICAL_ERROR, |
| 1267 | "Found multiple source steps for query\n{}\nPlan\n{}", |
| 1268 | ast->formatForErrorMessage(), buf.str()); |
| 1269 | } |
| 1270 | |
| 1271 | source = with_filter; |
| 1272 | } |
| 1273 | } |
| 1274 | |
| 1275 | if (!source) |
| 1276 | return nullptr; |
| 1277 | |
| 1278 | return source->detachFilterActionsDAG(); |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | std::optional<QueryPipeline> StorageDistributed::distributedWriteFromClusterStorage( |
no test coverage detected