1 | #pragma once |
2 | |
3 | #include <Core/Types.h> |
4 | #include <Parsers/IAST_fwd.h> |
5 | #include <Storages/IStorage_fwd.h> |
6 | |
7 | #include <string> |
8 | #include <memory> |
9 | |
10 | |
11 | namespace DB |
12 | { |
13 | |
14 | class ASTSelectQuery; |
15 | class Context; |
16 | |
17 | |
18 | /** Scheme of operation: |
19 | * |
20 | * If "main" table in a query is distributed enough (thus, have at least two shards), |
21 | * and there are non-GLOBAL subqueries in IN or JOIN, |
22 | * and in that subqueries, there is a table |
23 | * (in any nesting level in that subquery or in more deep subqueries), |
24 | * that exist on local server and (according to information on local server) is also distributed enough |
25 | * then, according to setting 'distributed_product_mode', |
26 | * either |
27 | * - throw an exception; |
28 | * - or add GLOBAL to top subquery; |
29 | * - or replace database and table name in subquery to remote database and table name, |
30 | * as Distributed storage on local server knows it. |
31 | * |
32 | * Do not recursively preprocess subqueries, as it will be done by calling code. |
33 | */ |
34 | |
35 | class InJoinSubqueriesPreprocessor |
36 | { |
37 | public: |
38 | struct CheckShardsAndTables |
39 | { |
40 | using Ptr = std::unique_ptr<CheckShardsAndTables>; |
41 | |
42 | /// These methods could be overriden for the need of the unit test. |
43 | virtual bool hasAtLeastTwoShards(const IStorage & table) const; |
44 | virtual std::pair<std::string, std::string> getRemoteDatabaseAndTableName(const IStorage & table) const; |
45 | virtual ~CheckShardsAndTables() {} |
46 | }; |
47 | |
48 | InJoinSubqueriesPreprocessor(const Context & context_, CheckShardsAndTables::Ptr _checker = std::make_unique<CheckShardsAndTables>()) |
49 | : context(context_) |
50 | , checker(std::move(_checker)) |
51 | {} |
52 | |
53 | void visit(ASTPtr & query) const; |
54 | |
55 | private: |
56 | const Context & context; |
57 | CheckShardsAndTables::Ptr checker; |
58 | }; |
59 | |
60 | |
61 | } |
62 | |