Throw for alter and silence for drop

This commit is contained in:
kssenii 2021-08-23 11:26:54 +00:00
parent 945e2c4ce5
commit 5307d31924
13 changed files with 56 additions and 4 deletions

View File

@ -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>

View File

@ -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(); }

View File

@ -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() {}

View File

@ -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;

View File

@ -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

View File

@ -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());
} }

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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();
} }

View File

@ -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")