@@ -144,6 +144,7 @@ StorageMerge::StorageMerge(
144
144
bool database_is_regexp_,
145
145
const DBToTableSetMap & source_databases_and_tables_,
146
146
const std::optional<String> & table_to_write_,
147
+ bool table_to_write_auto_,
147
148
ContextPtr context_)
148
149
: IStorage(table_id_)
149
150
, WithContext(context_->getGlobalContext ())
@@ -152,13 +153,15 @@ StorageMerge::StorageMerge(
152
153
database_is_regexp_,
153
154
source_database_name_or_regexp_, {},
154
155
source_databases_and_tables_)
156
+ , table_to_write_auto(table_to_write_auto_)
155
157
{
156
158
StorageInMemoryMetadata storage_metadata;
157
159
storage_metadata.setColumns (columns_.empty () ? getColumnsDescriptionFromSourceTables () : columns_);
158
160
storage_metadata.setComment (comment);
159
161
setInMemoryMetadata (storage_metadata);
160
162
setVirtuals (createVirtuals ());
161
- setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
163
+ if (!table_to_write_auto)
164
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
162
165
}
163
166
164
167
StorageMerge::StorageMerge (
@@ -169,6 +172,7 @@ StorageMerge::StorageMerge(
169
172
bool database_is_regexp_,
170
173
const String & source_table_regexp_,
171
174
const std::optional<String> & table_to_write_,
175
+ bool table_to_write_auto_,
172
176
ContextPtr context_)
173
177
: IStorage(table_id_)
174
178
, WithContext(context_->getGlobalContext ())
@@ -177,13 +181,15 @@ StorageMerge::StorageMerge(
177
181
database_is_regexp_,
178
182
source_database_name_or_regexp_,
179
183
source_table_regexp_, {})
184
+ , table_to_write_auto(table_to_write_auto_)
180
185
{
181
186
StorageInMemoryMetadata storage_metadata;
182
187
storage_metadata.setColumns (columns_.empty () ? getColumnsDescriptionFromSourceTables () : columns_);
183
188
storage_metadata.setComment (comment);
184
189
setInMemoryMetadata (storage_metadata);
185
190
setVirtuals (createVirtuals ());
186
- setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
191
+ if (!table_to_write_auto)
192
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
187
193
}
188
194
189
195
StorageMerge::DatabaseTablesIterators StorageMerge::getDatabaseIterators (ContextPtr context_) const
@@ -230,6 +236,29 @@ void StorageMerge::forEachTable(F && func) const
230
236
});
231
237
}
232
238
239
+ template <typename F>
240
+ void StorageMerge::forEachTableName (F && func) const
241
+ {
242
+ auto database_table_iterators = database_name_or_regexp.getDatabaseIterators (getContext ());
243
+
244
+ for (auto & iterator : database_table_iterators)
245
+ {
246
+ while (iterator->isValid ())
247
+ {
248
+ const auto & table = iterator->table ();
249
+ if (table.get () != this )
250
+ {
251
+ QualifiedTableName table_name;
252
+ table_name.database = iterator->databaseName ();
253
+ table_name.table = iterator->name ();
254
+ func (table_name);
255
+ }
256
+
257
+ iterator->next ();
258
+ }
259
+ }
260
+ }
261
+
233
262
bool StorageMerge::isRemote () const
234
263
{
235
264
auto first_remote_table = getFirstTable ([](const StoragePtr & table) { return table && table->isRemote (); });
@@ -1702,6 +1731,18 @@ SinkToStoragePtr StorageMerge::write(
1702
1731
ContextPtr context_,
1703
1732
bool async_insert)
1704
1733
{
1734
+ if (table_to_write_auto)
1735
+ {
1736
+ table_to_write = std::nullopt;
1737
+ forEachTableName ([&](const auto & table_name)
1738
+ {
1739
+ if (!table_to_write.has_value ())
1740
+ table_to_write = table_name;
1741
+ else if (table_to_write->getFullName () < table_name.getFullName ())
1742
+ table_to_write = table_name;
1743
+ });
1744
+ }
1745
+
1705
1746
if (!table_to_write.has_value ())
1706
1747
throw Exception (ErrorCodes::NOT_IMPLEMENTED, " Method write is not allowed in storage {} without described table to write." , getName ());
1707
1748
@@ -1738,14 +1779,23 @@ void registerStorageMerge(StorageFactory & factory)
1738
1779
String table_name_regexp = checkAndGetLiteralArgument<String>(engine_args[1 ], " table_name_regexp" );
1739
1780
1740
1781
std::optional<String> table_to_write = std::nullopt;
1782
+ bool table_to_write_auto = false ;
1741
1783
if (size == 3 )
1742
1784
{
1785
+ bool is_identifier = engine_args[2 ]->as <ASTIdentifier>();
1743
1786
engine_args[2 ] = evaluateConstantExpressionOrIdentifierAsLiteral (engine_args[2 ], args.getLocalContext ());
1744
1787
table_to_write = checkAndGetLiteralArgument<String>(engine_args[2 ], " table_to_write" );
1788
+ if (is_identifier && table_to_write == " auto" )
1789
+ {
1790
+ if (is_regexp)
1791
+ throw Exception (ErrorCodes::BAD_ARGUMENTS, " RegExp for database with auto table_to_write is forbidden." );
1792
+ table_to_write_auto = true ;
1793
+ }
1745
1794
}
1746
1795
1747
1796
return std::make_shared<StorageMerge>(
1748
- args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp, table_name_regexp, table_to_write, args.getContext ());
1797
+ args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp,
1798
+ table_name_regexp, table_to_write, table_to_write_auto, args.getContext ());
1749
1799
},
1750
1800
{
1751
1801
.supports_schema_inference = true
0 commit comments