diff --git a/src/Interpreters/TreeRewriter.cpp b/src/Interpreters/TreeRewriter.cpp index 1ad22efc3fc..2dc9a4ee818 100644 --- a/src/Interpreters/TreeRewriter.cpp +++ b/src/Interpreters/TreeRewriter.cpp @@ -624,14 +624,13 @@ void TreeRewriterResult::collectUsedColumns(const ASTPtr & query, bool is_select for (const auto & name : columns_context.requiredColumns()) ss << " '" << name << "'"; - if (!source_column_names.empty()) + ss << ", maybe you meant: "; + for (const auto & name : columns_context.requiredColumns()) { - ss << ", source columns:"; - for (const auto & name : source_column_names) - ss << " '" << name << "'"; + auto hints = storage->getHints(name); + if (!hints.empty()) + ss << " '" << toString(hints) << " '"; } - else - ss << ", no source columns"; if (columns_context.has_table_join) { diff --git a/src/Storages/IStorage.cpp b/src/Storages/IStorage.cpp index 94f37254b91..e0863094f5f 100644 --- a/src/Storages/IStorage.cpp +++ b/src/Storages/IStorage.cpp @@ -17,7 +17,6 @@ namespace DB { - namespace ErrorCodes { extern const int TABLE_IS_DROPPED; @@ -32,17 +31,18 @@ bool IStorage::isVirtualColumn(const String & column_name, const StorageMetadata } RWLockImpl::LockHolder IStorage::tryLockTimed( - const RWLock & rwlock, RWLockImpl::Type type, const String & query_id, const std::chrono::milliseconds & acquire_timeout) const + const RWLock & rwlock, RWLockImpl::Type type, const String & query_id, const std::chrono::milliseconds & acquire_timeout) const { auto lock_holder = rwlock->getLock(type, query_id, acquire_timeout); if (!lock_holder) { const String type_str = type == RWLockImpl::Type::Read ? "READ" : "WRITE"; throw Exception( - type_str + " locking attempt on \"" + getStorageID().getFullTableName() + - "\" has timed out! (" + std::to_string(acquire_timeout.count()) + "ms) " - "Possible deadlock avoided. Client should retry.", - ErrorCodes::DEADLOCK_AVOIDED); + type_str + " locking attempt on \"" + getStorageID().getFullTableName() + "\" has timed out! (" + + std::to_string(acquire_timeout.count()) + + "ms) " + "Possible deadlock avoided. Client should retry.", + ErrorCodes::DEADLOCK_AVOIDED); } return lock_holder; } @@ -82,26 +82,26 @@ TableExclusiveLockHolder IStorage::lockExclusively(const String & query_id, cons } Pipe IStorage::read( - const Names & /*column_names*/, - const StorageMetadataPtr & /*metadata_snapshot*/, - SelectQueryInfo & /*query_info*/, - const Context & /*context*/, - QueryProcessingStage::Enum /*processed_stage*/, - size_t /*max_block_size*/, - unsigned /*num_streams*/) + const Names & /*column_names*/, + const StorageMetadataPtr & /*metadata_snapshot*/, + SelectQueryInfo & /*query_info*/, + const Context & /*context*/, + QueryProcessingStage::Enum /*processed_stage*/, + size_t /*max_block_size*/, + unsigned /*num_streams*/) { throw Exception("Method read is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED); } void IStorage::read( - QueryPlan & query_plan, - const Names & column_names, - const StorageMetadataPtr & metadata_snapshot, - SelectQueryInfo & query_info, - const Context & context, - QueryProcessingStage::Enum processed_stage, - size_t max_block_size, - unsigned num_streams) + QueryPlan & query_plan, + const Names & column_names, + const StorageMetadataPtr & metadata_snapshot, + SelectQueryInfo & query_info, + const Context & context, + QueryProcessingStage::Enum processed_stage, + size_t max_block_size, + unsigned num_streams) { auto pipe = read(column_names, metadata_snapshot, query_info, context, processed_stage, max_block_size, num_streams); if (pipe.empty()) @@ -117,15 +117,12 @@ void IStorage::read( } Pipe IStorage::alterPartition( - const StorageMetadataPtr & /* metadata_snapshot */, - const PartitionCommands & /* commands */, - const Context & /* context */) + const StorageMetadataPtr & /* metadata_snapshot */, const PartitionCommands & /* commands */, const Context & /* context */) { throw Exception("Partition operations are not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED); } -void IStorage::alter( - const AlterCommands & params, const Context & context, TableLockHolder &) +void IStorage::alter(const AlterCommands & params, const Context & context, TableLockHolder &) { auto table_id = getStorageID(); StorageInMemoryMetadata new_metadata = getInMemoryMetadata(); @@ -146,7 +143,8 @@ void IStorage::checkAlterIsPossible(const AlterCommands & commands, const Settin } } -void IStorage::checkAlterPartitionIsPossible(const PartitionCommands & /*commands*/, const StorageMetadataPtr & /*metadata_snapshot*/, const Settings & /*settings*/) const +void IStorage::checkAlterPartitionIsPossible( + const PartitionCommands & /*commands*/, const StorageMetadataPtr & /*metadata_snapshot*/, const Settings & /*settings*/) const { throw Exception("Table engine " + getName() + " doesn't support partitioning", ErrorCodes::NOT_IMPLEMENTED); } @@ -168,4 +166,13 @@ NamesAndTypesList IStorage::getVirtuals() const return {}; } +Names IStorage::getAllRegisteredNames() const +{ + Names result; + auto getter = [](const auto & column) { return column.name; }; + const NamesAndTypesList & available_columns = getInMemoryMetadata().getColumns().getAllPhysical(); + std::transform(available_columns.begin(), available_columns.end(), std::back_inserter(result), getter); + return result; +} + } diff --git a/src/Storages/IStorage.h b/src/Storages/IStorage.h index 61ce207a09d..9d5a1fe85a9 100644 --- a/src/Storages/IStorage.h +++ b/src/Storages/IStorage.h @@ -78,7 +78,7 @@ struct ColumnSize * - data storage structure (compression, etc.) * - concurrent access to data (locks, etc.) */ -class IStorage : public std::enable_shared_from_this, public TypePromotion +class IStorage : public std::enable_shared_from_this, public TypePromotion, public IHints<1, IStorage> { public: IStorage() = delete; @@ -87,7 +87,7 @@ public: : storage_id(std::move(storage_id_)) , metadata(std::make_unique()) {} //-V730 - virtual ~IStorage() = default; + virtual ~IStorage() override = default; IStorage(const IStorage &) = delete; IStorage & operator=(const IStorage &) = delete; @@ -169,6 +169,7 @@ public: /// By default return empty list of columns. virtual NamesAndTypesList getVirtuals() const; + Names getAllRegisteredNames() const override; protected: /// Returns whether the column is virtual - by default all columns are real.