1#include <Common/OptimizedRegularExpression.h>
2#include <Common/typeid_cast.h>
3#include <Storages/StorageMerge.h>
4#include <Parsers/ASTLiteral.h>
5#include <Parsers/ASTFunction.h>
6#include <TableFunctions/ITableFunction.h>
7#include <Interpreters/evaluateConstantExpression.h>
8#include <Interpreters/Context.h>
9#include <TableFunctions/TableFunctionMerge.h>
10#include <TableFunctions/TableFunctionFactory.h>
11#include "registerTableFunctions.h"
12
13
14namespace DB
15{
16
17
18namespace ErrorCodes
19{
20 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
21 extern const int UNKNOWN_TABLE;
22}
23
24
25static NamesAndTypesList chooseColumns(const String & source_database, const String & table_name_regexp_, const Context & context)
26{
27 OptimizedRegularExpression table_name_regexp(table_name_regexp_);
28 auto table_name_match = [&](const String & table_name) { return table_name_regexp.match(table_name); };
29
30 StoragePtr any_table;
31
32 {
33 auto database = context.getDatabase(source_database);
34 auto iterator = database->getTablesIterator(context, table_name_match);
35
36 if (iterator->isValid())
37 any_table = iterator->table();
38 }
39
40 if (!any_table)
41 throw Exception("Error while executing table function merge. In database " + source_database + " no one matches regular expression: "
42 + table_name_regexp_, ErrorCodes::UNKNOWN_TABLE);
43
44 return any_table->getColumns().getAllPhysical();
45}
46
47
48StoragePtr TableFunctionMerge::executeImpl(const ASTPtr & ast_function, const Context & context, const std::string & table_name) const
49{
50 ASTs & args_func = ast_function->children;
51
52 if (args_func.size() != 1)
53 throw Exception("Table function 'merge' requires exactly 2 arguments"
54 " - name of source database and regexp for table names.",
55 ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
56
57 ASTs & args = args_func.at(0)->children;
58
59 if (args.size() != 2)
60 throw Exception("Table function 'merge' requires exactly 2 arguments"
61 " - name of source database and regexp for table names.",
62 ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
63
64 args[0] = evaluateConstantExpressionOrIdentifierAsLiteral(args[0], context);
65 args[1] = evaluateConstantExpressionAsLiteral(args[1], context);
66
67 String source_database = args[0]->as<ASTLiteral &>().value.safeGet<String>();
68 String table_name_regexp = args[1]->as<ASTLiteral &>().value.safeGet<String>();
69
70 auto res = StorageMerge::create(
71 getDatabaseName(),
72 table_name,
73 ColumnsDescription{chooseColumns(source_database, table_name_regexp, context)},
74 source_database,
75 table_name_regexp,
76 context);
77 res->startup();
78 return res;
79}
80
81
82void registerTableFunctionMerge(TableFunctionFactory & factory)
83{
84 factory.registerFunction<TableFunctionMerge>();
85}
86
87}
88