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
11namespace DB
12{
13
14class ASTSelectQuery;
15class 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
35class InJoinSubqueriesPreprocessor
36{
37public:
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
55private:
56 const Context & context;
57 CheckShardsAndTables::Ptr checker;
58};
59
60
61}
62