1 | #include <Databases/DatabaseDictionary.h> |
2 | #include <Databases/DatabaseFactory.h> |
3 | #include <Databases/DatabaseLazy.h> |
4 | #include <Databases/DatabaseMemory.h> |
5 | #include <Databases/DatabaseOrdinary.h> |
6 | #include <Parsers/ASTLiteral.h> |
7 | #include <Parsers/formatAST.h> |
8 | #include <Parsers/ASTCreateQuery.h> |
9 | #include <Parsers/ASTFunction.h> |
10 | #include <Common/parseAddress.h> |
11 | #include "config_core.h" |
12 | #include "DatabaseFactory.h" |
13 | #include <Poco/File.h> |
14 | |
15 | #if USE_MYSQL |
16 | |
17 | #include <Databases/DatabaseMySQL.h> |
18 | |
19 | #endif |
20 | |
21 | |
22 | namespace DB |
23 | { |
24 | |
25 | namespace ErrorCodes |
26 | { |
27 | extern const int BAD_ARGUMENTS; |
28 | extern const int UNKNOWN_DATABASE_ENGINE; |
29 | extern const int CANNOT_CREATE_DATABASE; |
30 | } |
31 | |
32 | DatabasePtr DatabaseFactory::get( |
33 | const String & database_name, const String & metadata_path, const ASTStorage * engine_define, Context & context) |
34 | { |
35 | try |
36 | { |
37 | Poco::File(metadata_path).createDirectory(); |
38 | return getImpl(database_name, metadata_path, engine_define, context); |
39 | } |
40 | catch (...) |
41 | { |
42 | Poco::File metadata_dir(metadata_path); |
43 | |
44 | if (metadata_dir.exists()) |
45 | metadata_dir.remove(true); |
46 | |
47 | throw; |
48 | } |
49 | } |
50 | |
51 | DatabasePtr DatabaseFactory::getImpl( |
52 | const String & database_name, const String & metadata_path, const ASTStorage * engine_define, Context & context) |
53 | { |
54 | String engine_name = engine_define->engine->name; |
55 | |
56 | if (engine_name != "MySQL" && engine_name != "Lazy" && engine_define->engine->arguments) |
57 | throw Exception("Database engine " + engine_name + " cannot have arguments" , ErrorCodes::BAD_ARGUMENTS); |
58 | |
59 | if (engine_define->engine->parameters || engine_define->partition_by || engine_define->primary_key || engine_define->order_by || |
60 | engine_define->sample_by || engine_define->settings) |
61 | throw Exception("Database engine " + engine_name + " cannot have parameters, primary_key, order_by, sample_by, settings" , |
62 | ErrorCodes::UNKNOWN_ELEMENT_IN_AST); |
63 | |
64 | if (engine_name == "Ordinary" ) |
65 | return std::make_shared<DatabaseOrdinary>(database_name, metadata_path, context); |
66 | else if (engine_name == "Memory" ) |
67 | return std::make_shared<DatabaseMemory>(database_name); |
68 | else if (engine_name == "Dictionary" ) |
69 | return std::make_shared<DatabaseDictionary>(database_name); |
70 | |
71 | #if USE_MYSQL |
72 | |
73 | else if (engine_name == "MySQL" ) |
74 | { |
75 | const ASTFunction * engine = engine_define->engine; |
76 | |
77 | if (!engine->arguments || engine->arguments->children.size() != 4) |
78 | throw Exception("MySQL Database require mysql_hostname, mysql_database_name, mysql_username, mysql_password arguments." , |
79 | ErrorCodes::BAD_ARGUMENTS); |
80 | |
81 | const auto & arguments = engine->arguments->children; |
82 | const auto & host_name_and_port = arguments[0]->as<ASTLiteral>()->value.safeGet<String>(); |
83 | const auto & database_name_in_mysql = arguments[1]->as<ASTLiteral>()->value.safeGet<String>(); |
84 | const auto & mysql_user_name = arguments[2]->as<ASTLiteral>()->value.safeGet<String>(); |
85 | const auto & mysql_user_password = arguments[3]->as<ASTLiteral>()->value.safeGet<String>(); |
86 | |
87 | try |
88 | { |
89 | const auto & [remote_host_name, remote_port] = parseAddress(host_name_and_port, 3306); |
90 | auto mysql_pool = mysqlxx::Pool(database_name_in_mysql, remote_host_name, mysql_user_name, mysql_user_password, remote_port); |
91 | |
92 | auto mysql_database = std::make_shared<DatabaseMySQL>( |
93 | context, database_name, metadata_path, engine_define, database_name_in_mysql, std::move(mysql_pool)); |
94 | |
95 | mysql_database->empty(context); /// test database is works fine. |
96 | return mysql_database; |
97 | } |
98 | catch (...) |
99 | { |
100 | const auto & exception_message = getCurrentExceptionMessage(true); |
101 | throw Exception("Cannot create MySQL database, because " + exception_message, ErrorCodes::CANNOT_CREATE_DATABASE); |
102 | } |
103 | } |
104 | |
105 | #endif |
106 | |
107 | else if (engine_name == "Lazy" ) |
108 | { |
109 | const ASTFunction * engine = engine_define->engine; |
110 | |
111 | if (!engine->arguments || engine->arguments->children.size() != 1) |
112 | throw Exception("Lazy database require cache_expiration_time_seconds argument" , ErrorCodes::BAD_ARGUMENTS); |
113 | |
114 | const auto & arguments = engine->arguments->children; |
115 | |
116 | const auto cache_expiration_time_seconds = arguments[0]->as<ASTLiteral>()->value.safeGet<UInt64>(); |
117 | return std::make_shared<DatabaseLazy>(database_name, metadata_path, cache_expiration_time_seconds, context); |
118 | } |
119 | |
120 | throw Exception("Unknown database engine: " + engine_name, ErrorCodes::UNKNOWN_DATABASE_ENGINE); |
121 | } |
122 | |
123 | } |
124 | |