@@ -144,6 +144,7 @@ StorageMerge::StorageMerge(
144144 bool database_is_regexp_,
145145 const DBToTableSetMap & source_databases_and_tables_,
146146 const std::optional<String> & table_to_write_,
147+ bool table_to_write_auto_,
147148 ContextPtr context_)
148149 : IStorage(table_id_)
149150 , WithContext(context_->getGlobalContext ())
@@ -152,13 +153,15 @@ StorageMerge::StorageMerge(
152153 database_is_regexp_,
153154 source_database_name_or_regexp_, {},
154155 source_databases_and_tables_)
156+ , table_to_write_auto(table_to_write_auto_)
155157{
156158 StorageInMemoryMetadata storage_metadata;
157159 storage_metadata.setColumns (columns_.empty () ? getColumnsDescriptionFromSourceTables () : columns_);
158160 storage_metadata.setComment (comment);
159161 setInMemoryMetadata (storage_metadata);
160162 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_);
162165}
163166
164167StorageMerge::StorageMerge (
@@ -169,6 +172,7 @@ StorageMerge::StorageMerge(
169172 bool database_is_regexp_,
170173 const String & source_table_regexp_,
171174 const std::optional<String> & table_to_write_,
175+ bool table_to_write_auto_,
172176 ContextPtr context_)
173177 : IStorage(table_id_)
174178 , WithContext(context_->getGlobalContext ())
@@ -177,13 +181,15 @@ StorageMerge::StorageMerge(
177181 database_is_regexp_,
178182 source_database_name_or_regexp_,
179183 source_table_regexp_, {})
184+ , table_to_write_auto(table_to_write_auto_)
180185{
181186 StorageInMemoryMetadata storage_metadata;
182187 storage_metadata.setColumns (columns_.empty () ? getColumnsDescriptionFromSourceTables () : columns_);
183188 storage_metadata.setComment (comment);
184189 setInMemoryMetadata (storage_metadata);
185190 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_);
187193}
188194
189195StorageMerge::DatabaseTablesIterators StorageMerge::getDatabaseIterators (ContextPtr context_) const
@@ -230,6 +236,29 @@ void StorageMerge::forEachTable(F && func) const
230236 });
231237}
232238
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+
233262bool StorageMerge::isRemote () const
234263{
235264 auto first_remote_table = getFirstTable ([](const StoragePtr & table) { return table && table->isRemote (); });
@@ -1702,6 +1731,18 @@ SinkToStoragePtr StorageMerge::write(
17021731 ContextPtr context_,
17031732 bool async_insert)
17041733{
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+
17051746 if (!table_to_write.has_value ())
17061747 throw Exception (ErrorCodes::NOT_IMPLEMENTED, " Method write is not allowed in storage {} without described table to write." , getName ());
17071748
@@ -1738,14 +1779,23 @@ void registerStorageMerge(StorageFactory & factory)
17381779 String table_name_regexp = checkAndGetLiteralArgument<String>(engine_args[1 ], " table_name_regexp" );
17391780
17401781 std::optional<String> table_to_write = std::nullopt ;
1782+ bool table_to_write_auto = false ;
17411783 if (size == 3 )
17421784 {
1785+ bool is_identifier = engine_args[2 ]->as <ASTIdentifier>();
17431786 engine_args[2 ] = evaluateConstantExpressionOrIdentifierAsLiteral (engine_args[2 ], args.getLocalContext ());
17441787 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+ }
17451794 }
17461795
17471796 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 ());
17491799 },
17501800 {
17511801 .supports_schema_inference = true
0 commit comments