better exception message in delete table with projection

This commit is contained in:
jsc0218 2024-05-22 04:35:06 +00:00
parent 6e33443926
commit 3f46e4e430
7 changed files with 51 additions and 1 deletions

View File

@ -25,6 +25,7 @@ namespace ErrorCodes
extern const int TABLE_IS_READ_ONLY;
extern const int SUPPORT_IS_DISABLED;
extern const int BAD_ARGUMENTS;
extern const int NOT_IMPLEMENTED;
}
@ -107,7 +108,19 @@ BlockIO InterpreterDeleteQuery::execute()
}
else
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "DELETE query is not supported for table {}", table->getStorageID().getFullTableName());
/// Currently just better exception for the case of a table with projection,
/// can act differently according to the setting.
if (table->hasProjection())
{
throw Exception(ErrorCodes::NOT_IMPLEMENTED,
"DELETE query is not supported for table {} as it has projections. "
"User should drop all the projections manually before running the query",
table->getStorageID().getFullTableName());
}
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"DELETE query is not supported for table {}",
table->getStorageID().getFullTableName());
}
}

View File

@ -259,6 +259,9 @@ public:
/// Return true if storage can execute lightweight delete mutations.
virtual bool supportsLightweightDelete() const { return false; }
/// Return true if storage has any projection.
virtual bool hasProjection() const { return false; }
/// Return true if storage can execute 'DELETE FROM' mutations. This is different from lightweight delete
/// because those are internally translated into 'ALTER UDPATE' mutations.
virtual bool supportsDelete() const { return false; }

View File

@ -442,6 +442,8 @@ public:
bool hasProjection(const String & projection_name) const { return projection_parts.contains(projection_name); }
bool hasProjection() const { return !projection_parts.empty(); }
bool hasBrokenProjection(const String & projection_name) const;
/// Return true, if all projections were loaded successfully and none was marked as broken.

View File

@ -6133,6 +6133,21 @@ bool MergeTreeData::supportsLightweightDelete() const
return true;
}
bool MergeTreeData::hasProjection() const
{
auto lock = lockParts();
for (const auto & part : data_parts_by_info)
{
if (part->getState() == MergeTreeDataPartState::Outdated
|| part->getState() == MergeTreeDataPartState::Deleting)
continue;
if (part->hasProjection())
return true;
}
return false;
}
MergeTreeData::ProjectionPartsVector MergeTreeData::getAllProjectionPartsVector(MergeTreeData::DataPartStateVector * out_states) const
{
ProjectionPartsVector res;

View File

@ -438,6 +438,8 @@ public:
bool supportsLightweightDelete() const override;
bool hasProjection() const override;
bool areAsynchronousInsertsEnabled() const override { return getSettings()->async_insert; }
bool supportsTrivialCountOptimization(const StorageSnapshotPtr &, ContextPtr) const override;

View File

@ -0,0 +1,15 @@
DROP TABLE IF EXISTS users;
CREATE TABLE users (
uid Int16,
name String,
age Int16,
projection p1 (select count(), age group by age)
) ENGINE = MergeTree order by uid;
INSERT INTO users VALUES (1231, 'John', 33);
INSERT INTO users VALUES (6666, 'Ksenia', 48);
INSERT INTO users VALUES (8888, 'Alice', 50);
DELETE FROM users WHERE 1; -- { serverError NOT_IMPLEMENTED }