mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +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 <common/logger_useful.h>
|
||||||
|
|
||||||
#include <IO/ReadWriteBufferFromHTTP.h>
|
#include <IO/ReadWriteBufferFromHTTP.h>
|
||||||
#include <IO/ReadIndirectBufferFromWebServer.h>
|
#include <Disks/ReadIndirectBufferFromWebServer.h>
|
||||||
#include <IO/SeekAvoidingReadBuffer.h>
|
#include <IO/SeekAvoidingReadBuffer.h>
|
||||||
#include <IO/ReadHelpers.h>
|
#include <IO/ReadHelpers.h>
|
||||||
#include <IO/WriteHelpers.h>
|
#include <IO/WriteHelpers.h>
|
||||||
|
@ -93,6 +93,8 @@ public:
|
|||||||
|
|
||||||
const String & getPath() const final override { return metadata_path; }
|
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 getTotalSpace() const final override { return std::numeric_limits<UInt64>::max(); }
|
||||||
|
|
||||||
UInt64 getAvailableSpace() 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.
|
/// Overrode in remote fs disks.
|
||||||
virtual bool supportZeroCopyReplication() const = 0;
|
virtual bool supportZeroCopyReplication() const = 0;
|
||||||
|
|
||||||
|
virtual bool isReadOnly() const { return false; }
|
||||||
|
|
||||||
/// Invoked when Global Context is shutdown.
|
/// Invoked when Global Context is shutdown.
|
||||||
virtual void shutdown() {}
|
virtual void shutdown() {}
|
||||||
|
|
||||||
|
@ -178,8 +178,6 @@ struct IDiskRemote::Metadata : RemoteMetadata
|
|||||||
static constexpr UInt32 VERSION_RELATIVE_PATHS = 2;
|
static constexpr UInt32 VERSION_RELATIVE_PATHS = 2;
|
||||||
static constexpr UInt32 VERSION_READ_ONLY_FLAG = 3;
|
static constexpr UInt32 VERSION_READ_ONLY_FLAG = 3;
|
||||||
|
|
||||||
using PathAndSize = std::pair<String, size_t>;
|
|
||||||
|
|
||||||
/// Disk path.
|
/// Disk path.
|
||||||
const String & disk_path;
|
const String & disk_path;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <IO/ReadBufferFromS3.h>
|
#include <IO/ReadBufferFromS3.h>
|
||||||
#include <Storages/HDFS/ReadBufferFromHDFS.h>
|
#include <Storages/HDFS/ReadBufferFromHDFS.h>
|
||||||
#include <IO/ReadIndirectBufferFromWebServer.h>
|
#include <Disks/ReadIndirectBufferFromWebServer.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
|
@ -58,6 +58,7 @@ bool ReadIndirectBufferFromWebServer::nextImpl()
|
|||||||
|
|
||||||
if (impl)
|
if (impl)
|
||||||
{
|
{
|
||||||
|
/// Restore correct position at the needed offset.
|
||||||
impl->position() = position();
|
impl->position() = position();
|
||||||
assert(!impl->hasPendingData());
|
assert(!impl->hasPendingData());
|
||||||
}
|
}
|
@ -32,6 +32,7 @@ namespace ErrorCodes
|
|||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
extern const int INCORRECT_QUERY;
|
extern const int INCORRECT_QUERY;
|
||||||
extern const int NOT_IMPLEMENTED;
|
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());
|
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 alter_lock = table->lockForAlter(getContext()->getCurrentQueryId(), getContext()->getSettingsRef().lock_acquire_timeout);
|
||||||
auto metadata_snapshot = table->getInMemoryMetadataPtr();
|
auto metadata_snapshot = table->getInMemoryMetadataPtr();
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ namespace ErrorCodes
|
|||||||
extern const int UNKNOWN_TABLE;
|
extern const int UNKNOWN_TABLE;
|
||||||
extern const int NOT_IMPLEMENTED;
|
extern const int NOT_IMPLEMENTED;
|
||||||
extern const int INCORRECT_QUERY;
|
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)
|
if (query.kind == ASTDropQuery::Kind::Detach)
|
||||||
{
|
{
|
||||||
getContext()->checkAccess(drop_storage, table_id);
|
getContext()->checkAccess(drop_storage, table_id);
|
||||||
|
if (table->isReadOnly())
|
||||||
|
throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is read-only");
|
||||||
|
|
||||||
if (table->isDictionary())
|
if (table->isDictionary())
|
||||||
{
|
{
|
||||||
@ -195,6 +198,8 @@ BlockIO InterpreterDropQuery::executeToTableImpl(ASTDropQuery & query, DatabaseP
|
|||||||
throw Exception("Cannot TRUNCATE dictionary", ErrorCodes::SYNTAX_ERROR);
|
throw Exception("Cannot TRUNCATE dictionary", ErrorCodes::SYNTAX_ERROR);
|
||||||
|
|
||||||
getContext()->checkAccess(AccessType::TRUNCATE, table_id);
|
getContext()->checkAccess(AccessType::TRUNCATE, table_id);
|
||||||
|
if (table->isReadOnly())
|
||||||
|
throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is read-only");
|
||||||
|
|
||||||
table->checkTableCanBeDropped();
|
table->checkTableCanBeDropped();
|
||||||
|
|
||||||
|
@ -201,6 +201,19 @@ NameDependencies IStorage::getDependentViewsByColumn(ContextPtr context) const
|
|||||||
return name_deps;
|
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
|
std::string PrewhereInfo::dump() const
|
||||||
{
|
{
|
||||||
WriteBufferFromOwnString ss;
|
WriteBufferFromOwnString ss;
|
||||||
|
@ -523,6 +523,9 @@ public:
|
|||||||
/// Returns storage policy if storage supports it.
|
/// Returns storage policy if storage supports it.
|
||||||
virtual StoragePolicyPtr getStoragePolicy() const { return {}; }
|
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.
|
/// If it is possible to quickly determine exact number of rows in the table at this moment of time, then return it.
|
||||||
/// Used for:
|
/// Used for:
|
||||||
/// - Simple count() optimization
|
/// - Simple count() optimization
|
||||||
|
@ -241,6 +241,9 @@ void StorageMergeTree::checkTableCanBeDropped() const
|
|||||||
void StorageMergeTree::drop()
|
void StorageMergeTree::drop()
|
||||||
{
|
{
|
||||||
shutdown();
|
shutdown();
|
||||||
|
/// In case there is read-only disk we cannot allow to call dropAllData(), but dropping tables is allowed.
|
||||||
|
if (isReadOnly())
|
||||||
|
return;
|
||||||
dropAllData();
|
dropAllData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,3 +60,25 @@ def test_usage(cluster):
|
|||||||
node2.query("DROP TABLE test{}".format(i))
|
node2.query("DROP TABLE test{}".format(i))
|
||||||
print(f"Ok {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