@@ -142,6 +142,7 @@ StorageMerge::StorageMerge(
142
142
const String & source_database_name_or_regexp_,
143
143
bool database_is_regexp_,
144
144
const DBToTableSetMap & source_databases_and_tables_,
145
+ const std::optional<String> & table_to_write_,
145
146
ContextPtr context_)
146
147
: IStorage(table_id_)
147
148
, WithContext(context_->getGlobalContext ())
@@ -158,6 +159,7 @@ StorageMerge::StorageMerge(
158
159
storage_metadata.setComment (comment);
159
160
setInMemoryMetadata (storage_metadata);
160
161
setVirtuals (createVirtuals ());
162
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
161
163
}
162
164
163
165
StorageMerge::StorageMerge (
@@ -167,6 +169,7 @@ StorageMerge::StorageMerge(
167
169
const String & source_database_name_or_regexp_,
168
170
bool database_is_regexp_,
169
171
const String & source_table_regexp_,
172
+ const std::optional<String> & table_to_write_,
170
173
ContextPtr context_)
171
174
: IStorage(table_id_)
172
175
, WithContext(context_->getGlobalContext ())
@@ -183,6 +186,7 @@ StorageMerge::StorageMerge(
183
186
storage_metadata.setComment (comment);
184
187
setInMemoryMetadata (storage_metadata);
185
188
setVirtuals (createVirtuals ());
189
+ setTableToWrite (table_to_write_, source_database_name_or_regexp_, database_is_regexp_);
186
190
}
187
191
188
192
StorageMerge::DatabaseTablesIterators StorageMerge::getDatabaseIterators (ContextPtr context_) const
@@ -1683,6 +1687,44 @@ std::optional<UInt64> StorageMerge::totalRowsOrBytes(F && func) const
1683
1687
return first_table ? std::nullopt : std::make_optional (total_rows_or_bytes);
1684
1688
}
1685
1689
1690
+ void StorageMerge::setTableToWrite (
1691
+ const std::optional<String> & table_to_write_,
1692
+ const String & source_database_name_or_regexp_,
1693
+ bool database_is_regexp_)
1694
+ {
1695
+ if (!table_to_write_.has_value ())
1696
+ {
1697
+ table_to_write = std::nullopt;
1698
+ return ;
1699
+ }
1700
+
1701
+ auto qualified_name = QualifiedTableName::parseFromString (*table_to_write_);
1702
+
1703
+ if (qualified_name.database .empty ())
1704
+ {
1705
+ if (database_is_regexp_)
1706
+ throw Exception (ErrorCodes::BAD_ARGUMENTS, " Argument 'table_to_write' must contain database if 'db_name' is regular expression." );
1707
+
1708
+ qualified_name.database = source_database_name_or_regexp_;
1709
+ }
1710
+
1711
+ table_to_write = qualified_name;
1712
+ }
1713
+
1714
+ SinkToStoragePtr StorageMerge::write (
1715
+ const ASTPtr & query,
1716
+ const StorageMetadataPtr & metadata_snapshot,
1717
+ ContextPtr context_,
1718
+ bool async_insert)
1719
+ {
1720
+ if (!table_to_write.has_value ())
1721
+ throw Exception (ErrorCodes::NOT_IMPLEMENTED, " Method write is not allowed in storage {} without described table to write." , getName ());
1722
+
1723
+ auto database = DatabaseCatalog::instance ().getDatabase (table_to_write->database );
1724
+ auto table = database->getTable (table_to_write->table , context_);
1725
+ return table->write (query, metadata_snapshot, context_, async_insert);
1726
+ }
1727
+
1686
1728
void registerStorageMerge (StorageFactory & factory)
1687
1729
{
1688
1730
factory.registerStorage (" Merge" , [](const StorageFactory::Arguments & args)
@@ -1693,10 +1735,12 @@ void registerStorageMerge(StorageFactory & factory)
1693
1735
1694
1736
ASTs & engine_args = args.engine_args ;
1695
1737
1696
- if (engine_args.size () != 2 )
1738
+ size_t size = engine_args.size ();
1739
+
1740
+ if (size < 2 || size > 3 )
1697
1741
throw Exception (ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
1698
- " Storage Merge requires exactly 2 parameters - name "
1699
- " of source database and regexp for table names." );
1742
+ " Storage Merge requires 2 or 3 parameters - name "
1743
+ " of source database, regexp for table names, and optional table name for writing ." );
1700
1744
1701
1745
auto [is_regexp, database_ast] = StorageMerge::evaluateDatabaseName (engine_args[0 ], args.getLocalContext ());
1702
1746
@@ -1708,8 +1752,15 @@ void registerStorageMerge(StorageFactory & factory)
1708
1752
engine_args[1 ] = evaluateConstantExpressionAsLiteral (engine_args[1 ], args.getLocalContext ());
1709
1753
String table_name_regexp = checkAndGetLiteralArgument<String>(engine_args[1 ], " table_name_regexp" );
1710
1754
1755
+ std::optional<String> table_to_write = std::nullopt;
1756
+ if (size == 3 )
1757
+ {
1758
+ engine_args[2 ] = evaluateConstantExpressionOrIdentifierAsLiteral (engine_args[2 ], args.getLocalContext ());
1759
+ table_to_write = checkAndGetLiteralArgument<String>(engine_args[2 ], " table_to_write" );
1760
+ }
1761
+
1711
1762
return std::make_shared<StorageMerge>(
1712
- args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp, table_name_regexp, args.getContext ());
1763
+ args.table_id , args.columns , args.comment , source_database_name_or_regexp, is_regexp, table_name_regexp, table_to_write, args.getContext ());
1713
1764
},
1714
1765
{
1715
1766
.supports_schema_inference = true
0 commit comments