diff --git a/src/Core/NamesAndTypes.cpp b/src/Core/NamesAndTypes.cpp index b8e9525c3b5..84913985c87 100644 --- a/src/Core/NamesAndTypes.cpp +++ b/src/Core/NamesAndTypes.cpp @@ -240,4 +240,19 @@ size_t NamesAndTypesList::getPosByName(const std::string &name) const noexcept return pos; } +String NamesAndTypesList::toNamesAndTypesDescription() const +{ + WriteBufferFromOwnString buf; + bool first = true; + for (const auto & name_and_type : *this) + { + if (!std::exchange(first, false)) + writeCString(", ", buf); + writeBackQuotedString(name_and_type.name, buf); + writeChar(' ', buf); + writeString(name_and_type.type->getName(), buf); + } + return buf.str(); +} + } diff --git a/src/Core/NamesAndTypes.h b/src/Core/NamesAndTypes.h index 466f5f37122..ba97d8b4592 100644 --- a/src/Core/NamesAndTypes.h +++ b/src/Core/NamesAndTypes.h @@ -122,6 +122,8 @@ public: /// Try to get column position by name, returns number of columns if column isn't found size_t getPosByName(const std::string & name) const noexcept; + + String toNamesAndTypesDescription() const; }; using NamesAndTypesLists = std::vector; diff --git a/src/Databases/DatabaseDictionary.cpp b/src/Databases/DatabaseDictionary.cpp index 04529ff5293..3a3dea1d38e 100644 --- a/src/Databases/DatabaseDictionary.cpp +++ b/src/Databases/DatabaseDictionary.cpp @@ -105,7 +105,7 @@ ASTPtr DatabaseDictionary::getCreateTableQueryImpl(const String & table_name, Co auto names_and_types = StorageDictionary::getNamesAndTypes(ExternalDictionariesLoader::getDictionaryStructure(*load_result.config)); buffer << "CREATE TABLE " << backQuoteIfNeed(getDatabaseName()) << '.' << backQuoteIfNeed(table_name) << " ("; - buffer << StorageDictionary::generateNamesAndTypesDescription(names_and_types); + buffer << names_and_types.toNamesAndTypesDescription(); buffer << ") Engine = Dictionary(" << backQuoteIfNeed(table_name) << ")"; } diff --git a/src/Storages/IStorageCluster.cpp b/src/Storages/IStorageCluster.cpp index 9eeed18e788..8bbe38b6949 100644 --- a/src/Storages/IStorageCluster.cpp +++ b/src/Storages/IStorageCluster.cpp @@ -77,7 +77,7 @@ Pipe IStorageCluster::read( const bool add_agg_info = processed_stage == QueryProcessingStage::WithMergeableState; if (!structure_argument_was_provided) - addColumnsStructureToQuery(query_to_send, StorageDictionary::generateNamesAndTypesDescription(storage_snapshot->metadata->getColumns().getAll()), context); + addColumnsStructureToQuery(query_to_send, storage_snapshot->metadata->getColumns().getAll().toNamesAndTypesDescription(), context); RestoreQualifiedNamesVisitor::Data data; data.distributed_table = DatabaseAndTableWithAlias(*getTableExpression(query_info.query->as(), 0)); diff --git a/src/Storages/StorageDictionary.cpp b/src/Storages/StorageDictionary.cpp index 09f972e4098..592195a918d 100644 --- a/src/Storages/StorageDictionary.cpp +++ b/src/Storages/StorageDictionary.cpp @@ -39,7 +39,7 @@ namespace { throw Exception(ErrorCodes::THERE_IS_NO_COLUMN, "Not found column {} {} in dictionary {}. There are only columns {}", column.name, column.type->getName(), backQuote(dictionary_name), - StorageDictionary::generateNamesAndTypesDescription(dictionary_names_and_types)); + dictionary_names_and_types.toNamesAndTypesDescription()); } } } @@ -80,20 +80,6 @@ NamesAndTypesList StorageDictionary::getNamesAndTypes(const DictionaryStructure return dictionary_names_and_types; } - -String StorageDictionary::generateNamesAndTypesDescription(const NamesAndTypesList & list) -{ - WriteBufferFromOwnString ss; - bool first = true; - for (const auto & name_and_type : list) - { - if (!std::exchange(first, false)) - ss << ", "; - ss << name_and_type.name << ' ' << name_and_type.type->getName(); - } - return ss.str(); -} - StorageDictionary::StorageDictionary( const StorageID & table_id_, const String & dictionary_name_, diff --git a/src/Storages/StorageDictionary.h b/src/Storages/StorageDictionary.h index 7d3ed01d185..aab704305e1 100644 --- a/src/Storages/StorageDictionary.h +++ b/src/Storages/StorageDictionary.h @@ -81,7 +81,6 @@ public: std::shared_ptr getDictionary() const; static NamesAndTypesList getNamesAndTypes(const DictionaryStructure & dictionary_structure); - static String generateNamesAndTypesDescription(const NamesAndTypesList & list); bool isDictionary() const override { return true; } void shutdown() override; diff --git a/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.reference b/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.reference new file mode 100644 index 00000000000..6c9c453e7b8 --- /dev/null +++ b/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.reference @@ -0,0 +1,2 @@ +a b c Nullable(UInt8) +42 diff --git a/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.sql b/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.sql new file mode 100644 index 00000000000..8c7cf212086 --- /dev/null +++ b/tests/queries/0_stateless/02876_s3_cluster_schema_inference_names_with_spaces.sql @@ -0,0 +1,6 @@ +-- Tags: no-fasttest +-- Tag no-fasttest: Depends on AWS + +desc s3Cluster(test_cluster_one_shard_three_replicas_localhost, 'http://localhost:11111/test/02876.parquet'); +select * from s3Cluster(test_cluster_one_shard_three_replicas_localhost, 'http://localhost:11111/test/02876.parquet'); + diff --git a/tests/queries/0_stateless/data_minio/02876.parquet b/tests/queries/0_stateless/data_minio/02876.parquet new file mode 100644 index 00000000000..fb1d1e17cb6 Binary files /dev/null and b/tests/queries/0_stateless/data_minio/02876.parquet differ