mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-29 02:52:13 +00:00
Throw for alter and silence for drop
This commit is contained in:
parent
945e2c4ce5
commit
5307d31924
@ -3,7 +3,7 @@
|
||||
#include <common/logger_useful.h>
|
||||
|
||||
#include <IO/ReadWriteBufferFromHTTP.h>
|
||||
#include <IO/ReadIndirectBufferFromWebServer.h>
|
||||
#include <Disks/ReadIndirectBufferFromWebServer.h>
|
||||
#include <IO/SeekAvoidingReadBuffer.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
|
||||
const String & getPath() const final override { return metadata_path; }
|
||||
|
||||
bool isReadOnly() const override { return true; }
|
||||
|
||||
UInt64 getTotalSpace() const final override { return std::numeric_limits<UInt64>::max(); }
|
||||
|
||||
UInt64 getAvailableSpace() const final override { return std::numeric_limits<UInt64>::max(); }
|
||||
|
@ -216,6 +216,8 @@ public:
|
||||
/// Overrode in remote fs disks.
|
||||
virtual bool supportZeroCopyReplication() const = 0;
|
||||
|
||||
virtual bool isReadOnly() const { return false; }
|
||||
|
||||
/// Invoked when Global Context is shutdown.
|
||||
virtual void shutdown() {}
|
||||
|
||||
|
@ -178,8 +178,6 @@ struct IDiskRemote::Metadata : RemoteMetadata
|
||||
static constexpr UInt32 VERSION_RELATIVE_PATHS = 2;
|
||||
static constexpr UInt32 VERSION_READ_ONLY_FLAG = 3;
|
||||
|
||||
using PathAndSize = std::pair<String, size_t>;
|
||||
|
||||
/// Disk path.
|
||||
const String & disk_path;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <IO/ReadBufferFromS3.h>
|
||||
#include <Storages/HDFS/ReadBufferFromHDFS.h>
|
||||
#include <IO/ReadIndirectBufferFromWebServer.h>
|
||||
#include <Disks/ReadIndirectBufferFromWebServer.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -58,6 +58,7 @@ bool ReadIndirectBufferFromWebServer::nextImpl()
|
||||
|
||||
if (impl)
|
||||
{
|
||||
/// Restore correct position at the needed offset.
|
||||
impl->position() = position();
|
||||
assert(!impl->hasPendingData());
|
||||
}
|
@ -32,6 +32,7 @@ namespace ErrorCodes
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int INCORRECT_QUERY;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
extern const int TABLE_IS_READ_ONLY;
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +63,8 @@ BlockIO InterpreterAlterQuery::execute()
|
||||
}
|
||||
|
||||
StoragePtr table = DatabaseCatalog::instance().getTable(table_id, getContext());
|
||||
if (table->isReadOnly())
|
||||
throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is read-only");
|
||||
auto alter_lock = table->lockForAlter(getContext()->getCurrentQueryId(), getContext()->getSettingsRef().lock_acquire_timeout);
|
||||
auto metadata_snapshot = table->getInMemoryMetadataPtr();
|
||||
|
||||
|
@ -34,6 +34,7 @@ namespace ErrorCodes
|
||||
extern const int UNKNOWN_TABLE;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
extern const int INCORRECT_QUERY;
|
||||
extern const int TABLE_IS_READ_ONLY;
|
||||
}
|
||||
|
||||
|
||||
@ -162,6 +163,8 @@ BlockIO InterpreterDropQuery::executeToTableImpl(ASTDropQuery & query, DatabaseP
|
||||
if (query.kind == ASTDropQuery::Kind::Detach)
|
||||
{
|
||||
getContext()->checkAccess(drop_storage, table_id);
|
||||
if (table->isReadOnly())
|
||||
throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is read-only");
|
||||
|
||||
if (table->isDictionary())
|
||||
{
|
||||
@ -195,6 +198,8 @@ BlockIO InterpreterDropQuery::executeToTableImpl(ASTDropQuery & query, DatabaseP
|
||||
throw Exception("Cannot TRUNCATE dictionary", ErrorCodes::SYNTAX_ERROR);
|
||||
|
||||
getContext()->checkAccess(AccessType::TRUNCATE, table_id);
|
||||
if (table->isReadOnly())
|
||||
throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is read-only");
|
||||
|
||||
table->checkTableCanBeDropped();
|
||||
|
||||
|
@ -201,6 +201,19 @@ NameDependencies IStorage::getDependentViewsByColumn(ContextPtr context) const
|
||||
return name_deps;
|
||||
}
|
||||
|
||||
bool IStorage::isReadOnly() const
|
||||
{
|
||||
auto storage_policy = getStoragePolicy();
|
||||
if (storage_policy)
|
||||
{
|
||||
for (const auto disk : storage_policy->getDisks())
|
||||
if (!disk->isReadOnly())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string PrewhereInfo::dump() const
|
||||
{
|
||||
WriteBufferFromOwnString ss;
|
||||
|
@ -523,6 +523,9 @@ public:
|
||||
/// Returns storage policy if storage supports it.
|
||||
virtual StoragePolicyPtr getStoragePolicy() const { return {}; }
|
||||
|
||||
/// Returns true if all disks of storage are read-only.
|
||||
virtual bool isReadOnly() const;
|
||||
|
||||
/// If it is possible to quickly determine exact number of rows in the table at this moment of time, then return it.
|
||||
/// Used for:
|
||||
/// - Simple count() optimization
|
||||
|
@ -241,6 +241,9 @@ void StorageMergeTree::checkTableCanBeDropped() const
|
||||
void StorageMergeTree::drop()
|
||||
{
|
||||
shutdown();
|
||||
/// In case there is read-only disk we cannot allow to call dropAllData(), but dropping tables is allowed.
|
||||
if (isReadOnly())
|
||||
return;
|
||||
dropAllData();
|
||||
}
|
||||
|
||||
|
@ -60,3 +60,25 @@ def test_usage(cluster):
|
||||
node2.query("DROP TABLE test{}".format(i))
|
||||
print(f"Ok {i}")
|
||||
|
||||
|
||||
def test_incorrect_usage(cluster):
|
||||
node1 = cluster.instances["node1"]
|
||||
node2 = cluster.instances["node2"]
|
||||
global uuids
|
||||
node2.query("""
|
||||
ATTACH TABLE test0 UUID '{}'
|
||||
(id Int32) ENGINE = MergeTree() ORDER BY id
|
||||
SETTINGS storage_policy = 'web';
|
||||
""".format(uuids[0]))
|
||||
|
||||
result = node2.query("SELECT count() FROM test0")
|
||||
assert(int(result) == 500000)
|
||||
|
||||
result = node2.query_and_get_error("ALTER TABLE test0 ADD COLUMN col1 Int32 first")
|
||||
assert("Table is read-only" in result)
|
||||
|
||||
result = node2.query_and_get_error("TRUNCATE TABLE test0")
|
||||
assert("Table is read-only" in result)
|
||||
|
||||
node2.query("DROP TABLE test0")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user