1#include <Storages/StorageFactory.h>
2#include <Interpreters/Context.h>
3#include <Parsers/ASTFunction.h>
4#include <Parsers/ASTCreateQuery.h>
5#include <Common/Exception.h>
6#include <Common/StringUtils/StringUtils.h>
7#include <IO/WriteHelpers.h>
8
9namespace DB
10{
11
12namespace ErrorCodes
13{
14 extern const int UNKNOWN_STORAGE;
15 extern const int LOGICAL_ERROR;
16 extern const int INCORRECT_QUERY;
17 extern const int ENGINE_REQUIRED;
18 extern const int FUNCTION_CANNOT_HAVE_PARAMETERS;
19 extern const int BAD_ARGUMENTS;
20 extern const int DATA_TYPE_CANNOT_BE_USED_IN_TABLES;
21}
22
23
24/// Some types are only for intermediate values of expressions and cannot be used in tables.
25static void checkAllTypesAreAllowedInTable(const NamesAndTypesList & names_and_types)
26{
27 for (const auto & elem : names_and_types)
28 if (elem.type->cannotBeStoredInTables())
29 throw Exception("Data type " + elem.type->getName() + " cannot be used in tables", ErrorCodes::DATA_TYPE_CANNOT_BE_USED_IN_TABLES);
30}
31
32
33void StorageFactory::registerStorage(const std::string & name, Creator creator)
34{
35 if (!storages.emplace(name, std::move(creator)).second)
36 throw Exception("TableFunctionFactory: the table function name '" + name + "' is not unique",
37 ErrorCodes::LOGICAL_ERROR);
38}
39
40
41StoragePtr StorageFactory::get(
42 const ASTCreateQuery & query,
43 const String & relative_data_path,
44 const String & table_name,
45 const String & database_name,
46 Context & local_context,
47 Context & context,
48 const ColumnsDescription & columns,
49 const ConstraintsDescription & constraints,
50 bool attach,
51 bool has_force_restore_data_flag) const
52{
53 String name;
54 ASTs args;
55 ASTStorage * storage_def = query.storage;
56
57 if (query.is_view)
58 {
59 if (query.storage)
60 throw Exception("Specifying ENGINE is not allowed for a View", ErrorCodes::INCORRECT_QUERY);
61
62 name = "View";
63 }
64 else if (query.is_live_view)
65 {
66
67 if (query.storage)
68 throw Exception("Specifying ENGINE is not allowed for a LiveView", ErrorCodes::INCORRECT_QUERY);
69
70 name = "LiveView";
71 }
72 else
73 {
74 /// Check for some special types, that are not allowed to be stored in tables. Example: NULL data type.
75 /// Exception: any type is allowed in View, because plain (non-materialized) View does not store anything itself.
76 checkAllTypesAreAllowedInTable(columns.getAll());
77
78 if (query.is_materialized_view)
79 {
80 name = "MaterializedView";
81 }
82 else
83 {
84 if (!storage_def)
85 throw Exception("Incorrect CREATE query: ENGINE required", ErrorCodes::ENGINE_REQUIRED);
86
87 const ASTFunction & engine_def = *storage_def->engine;
88
89 if (engine_def.parameters)
90 throw Exception(
91 "Engine definition cannot take the form of a parametric function", ErrorCodes::FUNCTION_CANNOT_HAVE_PARAMETERS);
92
93 if (engine_def.arguments)
94 args = engine_def.arguments->children;
95
96 name = engine_def.name;
97
98 if (storage_def->settings && !endsWith(name, "MergeTree") && name != "Kafka" && name != "Join")
99 {
100 throw Exception(
101 "Engine " + name + " doesn't support SETTINGS clause. "
102 "Currently only the MergeTree family of engines, Kafka engine and Join engine support it",
103 ErrorCodes::BAD_ARGUMENTS);
104 }
105
106 if ((storage_def->partition_by || storage_def->primary_key || storage_def->order_by || storage_def->sample_by ||
107 storage_def->ttl_table || !columns.getColumnTTLs().empty() ||
108 (query.columns_list && query.columns_list->indices && !query.columns_list->indices->children.empty()))
109 && !endsWith(name, "MergeTree"))
110 {
111 throw Exception(
112 "Engine " + name + " doesn't support PARTITION BY, PRIMARY KEY, ORDER BY, TTL or SAMPLE BY clauses and skipping indices. "
113 "Currently only the MergeTree family of engines supports them", ErrorCodes::BAD_ARGUMENTS);
114 }
115
116 if (name == "View")
117 {
118 throw Exception(
119 "Direct creation of tables with ENGINE View is not supported, use CREATE VIEW statement",
120 ErrorCodes::INCORRECT_QUERY);
121 }
122 else if (name == "MaterializedView")
123 {
124 throw Exception(
125 "Direct creation of tables with ENGINE MaterializedView is not supported, use CREATE MATERIALIZED VIEW statement",
126 ErrorCodes::INCORRECT_QUERY);
127 }
128 else if (name == "LiveView")
129 {
130 throw Exception(
131 "Direct creation of tables with ENGINE LiveView is not supported, use CREATE LIVE VIEW statement",
132 ErrorCodes::INCORRECT_QUERY);
133 }
134 }
135 }
136
137 auto it = storages.find(name);
138 if (it == storages.end())
139 {
140 auto hints = getHints(name);
141 if (!hints.empty())
142 throw Exception("Unknown table engine " + name + ". Maybe you meant: " + toString(hints), ErrorCodes::UNKNOWN_STORAGE);
143 else
144 throw Exception("Unknown table engine " + name, ErrorCodes::UNKNOWN_STORAGE);
145 }
146
147 Arguments arguments
148 {
149 .engine_name = name,
150 .engine_args = args,
151 .storage_def = storage_def,
152 .query = query,
153 .relative_data_path = relative_data_path,
154 .table_name = table_name,
155 .database_name = database_name,
156 .local_context = local_context,
157 .context = context,
158 .columns = columns,
159 .constraints = constraints,
160 .attach = attach,
161 .has_force_restore_data_flag = has_force_restore_data_flag
162 };
163
164 return it->second(arguments);
165}
166
167StorageFactory & StorageFactory::instance()
168{
169 static StorageFactory ret;
170 return ret;
171}
172
173}
174