@@ -143,6 +143,7 @@ StorageMerge::StorageMerge(
143
143
bool database_is_regexp_,
144
144
const DBToTableSetMap & source_databases_and_tables_,
145
145
const std::optional<String> & table_to_write_,
146
+ bool table_to_write_auto_,
146
147
ContextPtr context_)
147
148
: IStorage(table_id_)
148
149
, WithContext(context_->getGlobalContext ())
@@ -151,6 +152,7 @@ StorageMerge::StorageMerge(
151
152
database_is_regexp_,
152
153
source_database_name_or_regexp_, {},
153
154
source_databases_and_tables_)
155
+ , table_to_write_auto(table_to_write_auto_)
154
156
{
155
157
StorageInMemoryMetadata storage_metadata;
156
158
storage_metadata.setColumns (columns_.empty ()
@@ -159,7 +161,8 @@ StorageMerge::StorageMerge(
159
161
storage_metadata.setComment (comment);
160
162
setInMemoryMetadata (storage_metadata);
161
163
setVirtuals (createVirtuals ());
162
- setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
164
+ if (!table_to_write_auto)
165
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
163
166
}
164
167
165
168
StorageMerge::StorageMerge (
@@ -170,6 +173,7 @@ StorageMerge::StorageMerge(
170
173
bool database_is_regexp_,
171
174
const String & source_table_regexp_,
172
175
const std::optional<String> & table_to_write_,
176
+ bool table_to_write_auto_,
173
177
ContextPtr context_)
174
178
: IStorage(table_id_)
175
179
, WithContext(context_->getGlobalContext ())
@@ -178,6 +182,7 @@ StorageMerge::StorageMerge(
178
182
database_is_regexp_,
179
183
source_database_name_or_regexp_,
180
184
source_table_regexp_, {})
185
+ , table_to_write_auto(table_to_write_auto_)
181
186
{
182
187
StorageInMemoryMetadata storage_metadata;
183
188
storage_metadata.setColumns (columns_.empty ()
@@ -186,7 +191,8 @@ StorageMerge::StorageMerge(
186
191
storage_metadata.setComment (comment);
187
192
setInMemoryMetadata (storage_metadata);
188
193
setVirtuals (createVirtuals ());
189
- setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
194
+ if (!table_to_write_auto)
195
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
190
196
}
191
197
192
198
StorageMerge::DatabaseTablesIterators StorageMerge::getDatabaseIterators (ContextPtr context_) const
@@ -277,6 +283,29 @@ void StorageMerge::forEachTable(F && func) const
277
283
});
278
284
}
279
285
286
+ template <typename F>
287
+ void StorageMerge::forEachTableName (F && func) const
288
+ {
289
+ auto database_table_iterators = database_name_or_regexp.getDatabaseIterators (getContext ());
290
+
291
+ for (auto & iterator : database_table_iterators)
292
+ {
293
+ while (iterator->isValid ())
294
+ {
295
+ const auto & table = iterator->table ();
296
+ if (table.get () != this )
297
+ {
298
+ QualifiedTableName table_name;
299
+ table_name.database = iterator->databaseName ();
300
+ table_name.table = iterator->name ();
301
+ func (table_name);
302
+ }
303
+
304
+ iterator->next ();
305
+ }
306
+ }
307
+ }
308
+
280
309
bool StorageMerge::isRemote () const
281
310
{
282
311
auto first_remote_table = getFirstTable ([](const StoragePtr & table) { return table && table->isRemote (); });
@@ -1717,6 +1746,18 @@ SinkToStoragePtr StorageMerge::write(
1717
1746
ContextPtr context_,
1718
1747
bool async_insert)
1719
1748
{
1749
+ if (table_to_write_auto)
1750
+ {
1751
+ table_to_write = std::nullopt;
1752
+ forEachTableName ([&](const auto & table_name)
1753
+ {
1754
+ if (!table_to_write.has_value ())
1755
+ table_to_write = table_name;
1756
+ else if (table_to_write->getFullName () < table_name.getFullName ())
1757
+ table_to_write = table_name;
1758
+ });
1759
+ }
1760
+
1720
1761
if (!table_to_write.has_value ())
1721
1762
throw Exception (ErrorCodes::NOT_IMPLEMENTED, " Method write is not allowed in storage {} without described table to write." , getName ());
1722
1763
@@ -1753,14 +1794,23 @@ void registerStorageMerge(StorageFactory & factory)
1753
1794
String table_name_regexp = checkAndGetLiteralArgument<String>(engine_args[1 ], " table_name_regexp" );
1754
1795
1755
1796
std::optional<String> table_to_write = std::nullopt;
1797
+ bool table_to_write_auto = false ;
1756
1798
if (size == 3 )
1757
1799
{
1800
+ bool is_identifier = engine_args[2 ]->as <ASTIdentifier>();
1758
1801
engine_args[2 ] = evaluateConstantExpressionOrIdentifierAsLiteral (engine_args[2 ], args.getLocalContext ());
1759
1802
table_to_write = checkAndGetLiteralArgument<String>(engine_args[2 ], " table_to_write" );
1803
+ if (is_identifier && table_to_write == " auto" )
1804
+ {
1805
+ if (is_regexp)
1806
+ throw Exception (ErrorCodes::BAD_ARGUMENTS, " RegExp for database with auto table_to_write is forbidden." );
1807
+ table_to_write_auto = true ;
1808
+ }
1760
1809
}
1761
1810
1762
1811
return std::make_shared<StorageMerge>(
1763
- args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp, table_name_regexp, table_to_write, args.getContext ());
1812
+ args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp,
1813
+ table_name_regexp, table_to_write, table_to_write_auto, args.getContext ());
1764
1814
},
1765
1815
{
1766
1816
.supports_schema_inference = true
0 commit comments