Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0e31bd5
Call constructor of TemporaryTableHolder with creator
rvasin Jan 18, 2023
9fa4502
Add new constructor for TemporaryTableHolder
rvasin Jan 19, 2023
8453c9d
Add construction of temporary tables by StorageFactory
rvasin Jan 20, 2023
fa64203
Add correct data path for temporary tables; Clean temp DB dir on serv…
rvasin Jan 20, 2023
d898a42
Add possibility to create MergeTree tables
rvasin Jan 23, 2023
aa0f01a
Fix bug with DROP TEMPORARY TABLE for MergeTree
rvasin Jan 24, 2023
78c0a6a
Set Memory engine when there is no storage
rvasin Jan 24, 2023
640bb66
Move StorageFactory to top of doCreateTable for temp tables
rvasin Jan 24, 2023
16428b9
Fix removing data on disk for table engines like Log for DatabaseMemory
rvasin Jan 26, 2023
c09d8e7
Make MergeTree and Log table engines DROP and clean data
rvasin Jan 26, 2023
df4a9f1
Disallow creation of temporary tables with ON CLUSTER and with Replia…
rvasin Jan 30, 2023
c65e90d
Fix SHOW CREATE TEMPORARY TABLE
rvasin Jan 31, 2023
bfec300
Add 02525_different_engines_in_temporary_tables test
rvasin Feb 2, 2023
fa78c5b
Add TinyLog and StripeLog table engines to test
rvasin Feb 3, 2023
a4079bc
Update docs for temporary tables
rvasin Feb 6, 2023
9488bd8
Merge branch 'master' into ADQM-639
rvasin Feb 7, 2023
e20d3ce
Merge branch 'master' into ADQM-639
rvasin Feb 7, 2023
2b300e0
Fix setEngine() for temporary tables
rvasin Feb 7, 2023
bb465ce
Merge branch 'master' into ADQM-639
rvasin Feb 10, 2023
8cc768f
Add KeeperMap as disallowed engine for temporary tables
rvasin Feb 13, 2023
769ff6d
Merge branch 'ADQM-639' of github.com:arenadata/ClickHouse into ADQM-639
rvasin Feb 13, 2023
53298f5
Add test for ReplicatedMergeTree
rvasin Feb 14, 2023
42f2c53
Remove setting database for create query
rvasin Feb 14, 2023
b0ced21
Move temp database clean up into new function removeDataPath()
rvasin Feb 14, 2023
f410834
Remove dropTable of temp table from InterpreterDropQuery.
rvasin Feb 14, 2023
2524560
Add sessions test for temporary tables
rvasin Feb 17, 2023
fde8e7e
Add try/catch in TemporaryTableHolder destructor
rvasin Feb 17, 2023
3e2b56f
Merge branch 'master' into ADQM-639
rvasin Feb 17, 2023
5c1c519
Merge branch 'master' into ADQM-639
rvasin Feb 22, 2023
76dfb04
Send only temporary tables with StorageMemory
rvasin Feb 28, 2023
bb483ca
Update table.md doc
rvasin Feb 28, 2023
93dd929
Use INCORRECT_QUERY in test and add query with remote()
rvasin Feb 28, 2023
b5bb2eb
Add new grant CREATE ARBITRARY TEMPORARY TABLE
rvasin Mar 6, 2023
b14ab07
Fix failed tests
rvasin Mar 6, 2023
237b5b2
Update docs
rvasin Mar 6, 2023
95a7e11
Merge branch 'master' of github.com:ClickHouse/ClickHouse into ADQM-639
rvasin Mar 6, 2023
7dc0f87
Merge branch 'master' into ADQM-639
rvasin Mar 6, 2023
cf85915
Refactor grants logic, create test for grants, update docs
rvasin Mar 6, 2023
406b0f0
Add tests for grants of temporary tables with File and URL engines
rvasin Mar 7, 2023
f42f3ee
Merge branch 'master' into ADQM-639
rvasin Mar 9, 2023
36c639e
Fix grants hierarchy for temporary tables and comment about default e…
rvasin Mar 13, 2023
46d683f
Apply patch to fix grants hierarchy
rvasin Mar 16, 2023
419204a
Fix 01271_show_privileges test
rvasin Mar 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/en/sql-reference/statements/create/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ ENGINE = MergeTree ORDER BY x;
ClickHouse supports temporary tables which have the following characteristics:

- Temporary tables disappear when the session ends, including if the connection is lost.
- A temporary table uses the Memory engine only.
- A temporary table uses the Memory table engine when engine is not specified and it may use any table engine except Replicated and `KeeperMap` engines.
- The DB can’t be specified for a temporary table. It is created outside of databases.
- Impossible to create a temporary table with distributed DDL query on all cluster servers (by using `ON CLUSTER`): this table exists only in the current session.
- If a temporary table has the same name as another one and a query specifies the table name without specifying the DB, the temporary table will be used.
Expand All @@ -488,7 +488,7 @@ CREATE TEMPORARY TABLE [IF NOT EXISTS] table_name
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
)
) [ENGINE = engine]
```

In most cases, temporary tables are not created manually, but when using external data for a query, or for distributed `(GLOBAL) IN`. For more information, see the appropriate sections
Expand Down
6 changes: 4 additions & 2 deletions docs/en/sql-reference/statements/grant.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ Hierarchy of privileges:
- [CREATE](#grant-create)
- `CREATE DATABASE`
- `CREATE TABLE`
- `CREATE TEMPORARY TABLE`
- `CREATE ARBITRARY TEMPORARY TABLE`
- `CREATE TEMPORARY TABLE`
- `CREATE VIEW`
- `CREATE DICTIONARY`
- `CREATE FUNCTION`
Expand Down Expand Up @@ -313,7 +314,8 @@ Allows executing [CREATE](../../sql-reference/statements/create/index.md) and [A
- `CREATE`. Level: `GROUP`
- `CREATE DATABASE`. Level: `DATABASE`
- `CREATE TABLE`. Level: `TABLE`
- `CREATE TEMPORARY TABLE`. Level: `GLOBAL`
- `CREATE ARBITRARY TEMPORARY TABLE`. Level: `GLOBAL`
- `CREATE TEMPORARY TABLE`. Level: `GLOBAL`
- `CREATE VIEW`. Level: `VIEW`
- `CREATE DICTIONARY`. Level: `DICTIONARY`

Expand Down
16 changes: 8 additions & 8 deletions docs/ru/sql-reference/statements/create/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ ENGINE = MergeTree()

Кодеки шифрования:

- `CODEC('AES-128-GCM-SIV')` — Зашифровывает данные с помощью AES-128 в режиме [RFC 8452](https://tools.ietf.org/html/rfc8452) GCM-SIV.
- `CODEC('AES-256-GCM-SIV')` — Зашифровывает данные с помощью AES-256 в режиме GCM-SIV.
- `CODEC('AES-128-GCM-SIV')` — Зашифровывает данные с помощью AES-128 в режиме [RFC 8452](https://tools.ietf.org/html/rfc8452) GCM-SIV.
- `CODEC('AES-256-GCM-SIV')` — Зашифровывает данные с помощью AES-256 в режиме GCM-SIV.

Эти кодеки используют фиксированный одноразовый ключ шифрования. Таким образом, это детерминированное шифрование. Оно совместимо с поддерживающими дедупликацию движками, в частности, [ReplicatedMergeTree](../../../engines/table-engines/mergetree-family/replication.md). Однако у шифрования имеется недостаток: если дважды зашифровать один и тот же блок данных, текст на выходе получится одинаковым, и злоумышленник, у которого есть доступ к диску, заметит эту эквивалентность (при этом доступа к содержимому он не получит).

Expand All @@ -274,10 +274,10 @@ ENGINE = MergeTree()
**Пример**

```sql
CREATE TABLE mytable
CREATE TABLE mytable
(
x String Codec(AES_128_GCM_SIV)
)
)
ENGINE = MergeTree ORDER BY x;
```

Expand All @@ -287,10 +287,10 @@ ENGINE = MergeTree ORDER BY x;
**Пример**

```sql
CREATE TABLE mytable
CREATE TABLE mytable
(
x String Codec(Delta, LZ4, AES_128_GCM_SIV)
)
)
ENGINE = MergeTree ORDER BY x;
```

Expand All @@ -299,7 +299,7 @@ ENGINE = MergeTree ORDER BY x;
ClickHouse поддерживает временные таблицы со следующими характеристиками:

- Временные таблицы исчезают после завершения сессии, в том числе при обрыве соединения.
- Временная таблица использует только модуль памяти.
- Временная таблица использует движок таблиц Memory когда движок не указан и она может использовать любой движок таблиц за исключением движков Replicated и `KeeperMap`.
- Невозможно указать базу данных для временной таблицы. Она создается вне баз данных.
- Невозможно создать временную таблицу распределённым DDL запросом на всех серверах кластера (с опцией `ON CLUSTER`): такая таблица существует только в рамках существующей сессии.
- Если временная таблица имеет то же имя, что и некоторая другая, то, при упоминании в запросе без указания БД, будет использована временная таблица.
Expand All @@ -313,7 +313,7 @@ CREATE TEMPORARY TABLE [IF NOT EXISTS] table_name
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
)
) [ENGINE = engine]
```

В большинстве случаев, временные таблицы создаются не вручную, а при использовании внешних данных для запроса, или при распределённом `(GLOBAL) IN`. Подробнее см. соответствующие разделы
Expand Down
6 changes: 4 additions & 2 deletions docs/ru/sql-reference/statements/grant.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ GRANT SELECT(x,y) ON db.table TO john WITH GRANT OPTION
- [CREATE](#grant-create)
- `CREATE DATABASE`
- `CREATE TABLE`
- `CREATE TEMPORARY TABLE`
- `CREATE ARBITRARY TEMPORARY TABLE`
- `CREATE TEMPORARY TABLE`
- `CREATE VIEW`
- `CREATE DICTIONARY`
- `CREATE FUNCTION`
Expand Down Expand Up @@ -314,7 +315,8 @@ GRANT INSERT(x,y) ON db.table TO john
- `CREATE`. Уровень: `GROUP`
- `CREATE DATABASE`. Уровень: `DATABASE`
- `CREATE TABLE`. Уровень: `TABLE`
- `CREATE TEMPORARY TABLE`. Уровень: `GLOBAL`
- `CREATE ARBITRARY TEMPORARY TABLE`. Уровень: `GLOBAL`
- `CREATE TEMPORARY TABLE`. Уровень: `GLOBAL`
- `CREATE VIEW`. Уровень: `VIEW`
- `CREATE DICTIONARY`. Уровень: `DICTIONARY`

Expand Down
5 changes: 4 additions & 1 deletion src/Access/Common/AccessType.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum class AccessType
/// node_type either specifies access type's level (GLOBAL/DATABASE/TABLE/DICTIONARY/VIEW/COLUMNS),
/// or specifies that the access type is a GROUP of other access types;
/// parent_group_name is the name of the group containing this access type (or NONE if there is no such group).
/// NOTE A parent group must be declared AFTER all its children.
#define APPLY_FOR_ACCESS_TYPES(M) \
M(SHOW_DATABASES, "", DATABASE, SHOW) /* allows to execute SHOW DATABASES, SHOW CREATE DATABASE, USE <database>;
implicitly enabled by any grant on the database */\
Expand Down Expand Up @@ -86,8 +87,10 @@ enum class AccessType
M(CREATE_VIEW, "", VIEW, CREATE) /* allows to execute {CREATE|ATTACH} VIEW;
implicitly enabled by the grant CREATE_TABLE */\
M(CREATE_DICTIONARY, "", DICTIONARY, CREATE) /* allows to execute {CREATE|ATTACH} DICTIONARY */\
M(CREATE_TEMPORARY_TABLE, "", GLOBAL, CREATE) /* allows to create and manipulate temporary tables;
M(CREATE_TEMPORARY_TABLE, "", GLOBAL, CREATE_ARBITRARY_TEMPORARY_TABLE) /* allows to create and manipulate temporary tables;
implicitly enabled by the grant CREATE_TABLE on any table */ \
M(CREATE_ARBITRARY_TEMPORARY_TABLE, "", GLOBAL, CREATE) /* allows to create and manipulate temporary tables
with arbitrary table engine */\
M(CREATE_FUNCTION, "", GLOBAL, CREATE) /* allows to execute CREATE FUNCTION */ \
M(CREATE_NAMED_COLLECTION, "", GLOBAL, CREATE) /* allows to execute CREATE NAMED COLLECTION */ \
M(CREATE, "", GROUP, ALL) /* allows to execute {CREATE|ATTACH} */ \
Expand Down
5 changes: 5 additions & 0 deletions src/Access/ContextAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ namespace
if ((level == 0) && (max_flags_with_children & create_table))
res |= create_temporary_table;

/// CREATE TABLE (on any database/table) => CREATE_ARBITRARY_TEMPORARY_TABLE (global)
static const AccessFlags create_arbitrary_temporary_table = AccessType::CREATE_ARBITRARY_TEMPORARY_TABLE;
if ((level == 0) && (max_flags_with_children & create_table))
res |= create_arbitrary_temporary_table;

/// ALTER_TTL => ALTER_MATERIALIZE_TTL
static const AccessFlags alter_ttl = AccessType::ALTER_TTL;
static const AccessFlags alter_materialize_ttl = AccessType::ALTER_MATERIALIZE_TTL;
Expand Down
18 changes: 13 additions & 5 deletions src/Databases/DatabaseMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ namespace ErrorCodes
DatabaseMemory::DatabaseMemory(const String & name_, ContextPtr context_)
: DatabaseWithOwnTablesBase(name_, "DatabaseMemory(" + name_ + ")", context_)
, data_path("data/" + escapeForFileName(database_name) + "/")
{}
{
/// Temporary database should not have any data on the moment of its creation
/// In case of sudden server shutdown remove database folder of temporary database
if (name_ == DatabaseCatalog::TEMPORARY_DATABASE)
removeDataPath(context_);
}

void DatabaseMemory::createTable(
ContextPtr /*context*/,
Expand Down Expand Up @@ -71,16 +76,14 @@ void DatabaseMemory::dropTable(

if (table->storesDataOnDisk())
{
assert(getDatabaseName() != DatabaseCatalog::TEMPORARY_DATABASE);
fs::path table_data_dir{getTableDataPath(table_name)};
fs::path table_data_dir{fs::path{getContext()->getPath()} / getTableDataPath(table_name)};
if (fs::exists(table_data_dir))
fs::remove_all(table_data_dir);
}
}
catch (...)
{
std::lock_guard lock{mutex};
assert(database_name != DatabaseCatalog::TEMPORARY_DATABASE);
attachTableUnlocked(table_name, table);
throw;
}
Expand Down Expand Up @@ -129,10 +132,15 @@ UUID DatabaseMemory::tryGetTableUUID(const String & table_name) const
return UUIDHelpers::Nil;
}

void DatabaseMemory::removeDataPath(ContextPtr local_context)
{
std::filesystem::remove_all(local_context->getPath() + data_path);
}

void DatabaseMemory::drop(ContextPtr local_context)
{
/// Remove data on explicit DROP DATABASE
std::filesystem::remove_all(local_context->getPath() + data_path);
removeDataPath(local_context);
}

void DatabaseMemory::alterTable(ContextPtr local_context, const StorageID & table_id, const StorageInMemoryMetadata & metadata)
Expand Down
2 changes: 2 additions & 0 deletions src/Databases/DatabaseMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class DatabaseMemory final : public DatabaseWithOwnTablesBase
std::vector<std::pair<ASTPtr, StoragePtr>> getTablesForBackup(const FilterByNameFunction & filter, const ContextPtr & local_context) const override;

private:
void removeDataPath(ContextPtr local_context);

const String data_path;
using NameToASTCreate = std::unordered_map<String, ASTPtr>;
NameToASTCreate create_queries TSA_GUARDED_BY(mutex);
Expand Down
13 changes: 10 additions & 3 deletions src/Interpreters/DatabaseCatalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,16 @@ TemporaryTableHolder::~TemporaryTableHolder()
{
if (id != UUIDHelpers::Nil)
{
auto table = getTable();
table->flushAndShutdown();
temporary_tables->dropTable(getContext(), "_tmp_" + toString(id));
try
{
auto table = getTable();
table->flushAndShutdown();
temporary_tables->dropTable(getContext(), "_tmp_" + toString(id));
}
catch (...)
{
tryLogCurrentException("TemporaryTableHolder");
}
}
}

Expand Down
60 changes: 44 additions & 16 deletions src/Interpreters/InterpreterCreateQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -940,23 +940,32 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const

if (create.temporary)
{
if (create.storage && create.storage->engine && create.storage->engine->name != "Memory")
throw Exception(ErrorCodes::INCORRECT_QUERY, "Temporary tables can only be created with ENGINE = Memory, not {}",
create.storage->engine->name);

/// It's possible if some part of storage definition (such as PARTITION BY) is specified, but ENGINE is not.
/// It makes sense when default_table_engine setting is used, but not for temporary tables.
/// For temporary tables we ignore this setting to allow CREATE TEMPORARY TABLE query without specifying ENGINE
/// even if setting is set to MergeTree or something like that (otherwise MergeTree will be substituted and query will fail).
if (create.storage && !create.storage->engine)
throw Exception(ErrorCodes::INCORRECT_QUERY, "Invalid storage definition for temporary table: must be either ENGINE = Memory or empty");

auto engine_ast = std::make_shared<ASTFunction>();
engine_ast->name = "Memory";
engine_ast->no_empty_args = true;
auto storage_ast = std::make_shared<ASTStorage>();
storage_ast->set(storage_ast->engine, engine_ast);
create.set(create.storage, storage_ast);

if (!create.cluster.empty())
throw Exception(ErrorCodes::INCORRECT_QUERY, "Temporary tables cannot be created with ON CLUSTER clause");

if (create.storage)
{
if (create.storage->engine)
{
if (create.storage->engine->name.starts_with("Replicated") || create.storage->engine->name == "KeeperMap")
throw Exception(ErrorCodes::INCORRECT_QUERY, "Temporary tables cannot be created with Replicated or KeeperMap table engines");
}
else
throw Exception(ErrorCodes::INCORRECT_QUERY, "Invalid storage definition for temporary table");
}
else
{
auto engine_ast = std::make_shared<ASTFunction>();
engine_ast->name = "Memory";
engine_ast->no_empty_args = true;
auto storage_ast = std::make_shared<ASTStorage>();
storage_ast->set(storage_ast->engine, engine_ast);
create.set(create.storage, storage_ast);
}
return;
}

Expand Down Expand Up @@ -1284,8 +1293,21 @@ bool InterpreterCreateQuery::doCreateTable(ASTCreateQuery & create,
if (create.if_not_exists && getContext()->tryResolveStorageID({"", create.getTable()}, Context::ResolveExternal))
return false;

DatabasePtr database = DatabaseCatalog::instance().getDatabase(DatabaseCatalog::TEMPORARY_DATABASE);

String temporary_table_name = create.getTable();
auto temporary_table = TemporaryTableHolder(getContext(), properties.columns, properties.constraints, query_ptr);
auto creator = [&](const StorageID & table_id)
{
return StorageFactory::instance().get(create,
database->getTableDataPath(table_id.getTableName()),
getContext(),
getContext()->getGlobalContext(),
properties.columns,
properties.constraints,
false);
};
auto temporary_table = TemporaryTableHolder(getContext(), creator, query_ptr);

getContext()->getSessionContext()->addExternalTable(temporary_table_name, std::move(temporary_table));
return true;
}
Expand Down Expand Up @@ -1712,7 +1734,13 @@ AccessRightsElements InterpreterCreateQuery::getRequiredAccess() const
else
{
if (create.temporary)
required_access.emplace_back(AccessType::CREATE_TEMPORARY_TABLE);
{
/// Currently default table engine for temporary tables is Memory. default_table_engine does not affect temporary tables.
if (create.storage && create.storage->engine && create.storage->engine->name != "Memory")
required_access.emplace_back(AccessType::CREATE_ARBITRARY_TEMPORARY_TABLE);
else
required_access.emplace_back(AccessType::CREATE_TEMPORARY_TABLE);
}
else
{
if (create.replace_table)
Expand Down
5 changes: 0 additions & 5 deletions src/Interpreters/InterpreterDropQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,6 @@ BlockIO InterpreterDropQuery::executeToTemporaryTable(const String & table_name,
else if (kind == ASTDropQuery::Kind::Drop)
{
context_handle->removeExternalTable(table_name);
table->flushAndShutdown();
auto table_lock = table->lockExclusively(getContext()->getCurrentQueryId(), getContext()->getSettingsRef().lock_acquire_timeout);
/// Delete table data
table->drop();
table->is_dropped = true;
}
else if (kind == ASTDropQuery::Kind::Detach)
{
Expand Down
4 changes: 4 additions & 0 deletions src/QueryPipeline/RemoteQueryExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <Client/MultiplexedConnections.h>
#include <Client/HedgedConnections.h>
#include <Storages/MergeTree/MergeTreeDataPartUUID.h>
#include <Storages/StorageMemory.h>


namespace CurrentMetrics
Expand Down Expand Up @@ -601,6 +602,9 @@ void RemoteQueryExecutor::sendExternalTables()
for (const auto & table : external_tables)
{
StoragePtr cur = table.second;
/// Send only temporary tables with StorageMemory
if (!std::dynamic_pointer_cast<StorageMemory>(cur))
continue;

auto data = std::make_unique<ExternalTableData>();
data->table_name = table.first;
Expand Down
3 changes: 2 additions & 1 deletion tests/queries/0_stateless/01271_show_privileges.reference
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ CREATE DATABASE [] DATABASE CREATE
CREATE TABLE [] TABLE CREATE
CREATE VIEW [] VIEW CREATE
CREATE DICTIONARY [] DICTIONARY CREATE
CREATE TEMPORARY TABLE [] GLOBAL CREATE
CREATE TEMPORARY TABLE [] GLOBAL CREATE ARBITRARY TEMPORARY TABLE
CREATE ARBITRARY TEMPORARY TABLE [] GLOBAL CREATE
CREATE FUNCTION [] GLOBAL CREATE
CREATE NAMED COLLECTION [] GLOBAL CREATE
CREATE [] \N ALL
Expand Down
Loading