Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
4ff7bf78
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4ff7bf78
编写于
2月 03, 2020
作者:
A
Alexander Tokmakov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add DatabaseCatalog
上级
b7197ba5
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
410 addition
and
176 deletion
+410
-176
dbms/programs/local/LocalServer.cpp
dbms/programs/local/LocalServer.cpp
+2
-0
dbms/programs/server/Server.cpp
dbms/programs/server/Server.cpp
+2
-0
dbms/src/Databases/DatabaseMemory.h
dbms/src/Databases/DatabaseMemory.h
+1
-2
dbms/src/Interpreters/Context.cpp
dbms/src/Interpreters/Context.cpp
+71
-159
dbms/src/Interpreters/Context.h
dbms/src/Interpreters/Context.h
+13
-14
dbms/src/Interpreters/DatabaseCatalog.cpp
dbms/src/Interpreters/DatabaseCatalog.cpp
+228
-0
dbms/src/Interpreters/DatabaseCatalog.h
dbms/src/Interpreters/DatabaseCatalog.h
+91
-0
dbms/src/Interpreters/InterpreterShowTablesQuery.cpp
dbms/src/Interpreters/InterpreterShowTablesQuery.cpp
+2
-1
未找到文件。
dbms/programs/local/LocalServer.cpp
浏览文件 @
4ff7bf78
...
...
@@ -12,6 +12,7 @@
#include <Interpreters/ProcessList.h>
#include <Interpreters/executeQuery.h>
#include <Interpreters/loadMetadata.h>
#include <Interpreters/DatabaseCatalog.h>
#include <Common/Exception.h>
#include <Common/Macros.h>
#include <Common/Config/ConfigProcessor.h>
...
...
@@ -200,6 +201,7 @@ try
loadMetadataSystem
(
*
context
);
attachSystemTables
();
loadMetadata
(
*
context
);
context
->
getDatabaseCatalog
().
loadDatabases
();
LOG_DEBUG
(
log
,
"Loaded metadata."
);
}
else
...
...
dbms/programs/server/Server.cpp
浏览文件 @
4ff7bf78
...
...
@@ -41,6 +41,7 @@
#include <Interpreters/ExternalModelsLoader.h>
#include <Interpreters/ProcessList.h>
#include <Interpreters/loadMetadata.h>
#include <Interpreters/DatabaseCatalog.h>
#include <Interpreters/DNSCacheUpdater.h>
#include <Interpreters/SystemLog.cpp>
#include <Interpreters/ExternalLoaderXMLConfigRepository.h>
...
...
@@ -551,6 +552,7 @@ int Server::main(const std::vector<std::string> & /*args*/)
attachSystemTablesServer
(
*
global_context
->
getDatabase
(
"system"
),
has_zookeeper
);
/// Then, load remaining databases
loadMetadata
(
*
global_context
);
global_context
->
getDatabaseCatalog
().
loadDatabases
();
}
catch
(...)
{
...
...
dbms/src/Databases/DatabaseMemory.h
浏览文件 @
4ff7bf78
...
...
@@ -19,8 +19,7 @@ namespace DB
class
DatabaseMemory
:
public
DatabaseWithOwnTablesBase
{
public:
//FIXME default name
DatabaseMemory
(
const
String
&
name_
=
"_temporary_and_external_tables"
);
DatabaseMemory
(
const
String
&
name_
);
String
getEngineName
()
const
override
{
return
"Memory"
;
}
...
...
dbms/src/Interpreters/Context.cpp
浏览文件 @
4ff7bf78
...
...
@@ -59,6 +59,7 @@
#include <Common/RemoteHostFilter.h>
#include <Databases/DatabaseMemory.h>
#include <Interpreters/DatabaseCatalog.h>
namespace
ProfileEvents
{
...
...
@@ -103,10 +104,8 @@ namespace ErrorCodes
struct
TemporaryTableHolder
:
boost
::
noncopyable
{
static
constexpr
const
char
*
database_name
=
"_temporary_and_external_tables"
;
TemporaryTableHolder
(
const
Context
&
context_
,
DatabaseMemory
&
external_tables_
,
IDatabase
&
external_tables_
,
const
StoragePtr
&
table
,
const
ASTPtr
&
query
=
{})
:
context
(
context_
),
external_tables
(
external_tables_
)
...
...
@@ -136,7 +135,7 @@ struct TemporaryTableHolder : boost::noncopyable
StorageID
getGlobalTableID
()
const
{
return
StorageID
{
database_name
,
"_data_"
+
toString
(
id
),
id
};
return
StorageID
{
DatabaseCatalog
::
TEMPORARY_DATABASE
,
"_data_"
+
toString
(
id
),
id
};
}
StoragePtr
getTable
()
const
...
...
@@ -148,7 +147,7 @@ struct TemporaryTableHolder : boost::noncopyable
}
const
Context
&
context
;
DatabaseMemory
&
external_tables
;
IDatabase
&
external_tables
;
UUID
id
;
};
...
...
@@ -186,8 +185,7 @@ struct ContextShared
String
tmp_path
;
/// Path to the temporary files that occur when processing the request.
mutable
VolumePtr
tmp_volume
;
/// Volume for the the temporary files that occur when processing the request.
Databases
databases
;
/// List of databases and tables in them.
DatabaseMemory
temporary_and_external_tables
;
std
::
shared_ptr
<
DatabaseCatalog
>
database_catalog
;
/// Manages databases and tables in them.
mutable
std
::
optional
<
EmbeddedDictionaries
>
embedded_dictionaries
;
/// Metrica's dictionaries. Have lazy initialization.
mutable
std
::
optional
<
ExternalDictionariesLoader
>
external_dictionaries_loader
;
...
...
@@ -319,28 +317,7 @@ struct ContextShared
if
(
system_logs
)
system_logs
->
shutdown
();
/** At this point, some tables may have threads that block our mutex.
* To shutdown them correctly, we will copy the current list of tables,
* and ask them all to finish their work.
* Then delete all objects with tables.
*/
Databases
current_databases
;
{
std
::
lock_guard
lock
(
mutex
);
current_databases
=
databases
;
}
/// We still hold "databases" in Context (instead of std::move) for Buffer tables to flush data correctly.
for
(
auto
&
database
:
current_databases
)
database
.
second
->
shutdown
();
{
std
::
lock_guard
lock
(
mutex
);
databases
.
clear
();
}
database_catalog
->
shutdown
();
/// Preemptive destruction is important, because these objects may have a refcount to ContextShared (cyclic reference).
/// TODO: Get rid of this.
...
...
@@ -385,6 +362,7 @@ Context Context::createGlobal()
res
.
row_policy
=
std
::
make_shared
<
RowPolicyContext
>
();
res
.
access_rights
=
std
::
make_shared
<
AccessRightsContext
>
();
res
.
shared
=
std
::
make_shared
<
ContextShared
>
();
res
.
shared
->
database_catalog
=
std
::
make_shared
<
DatabaseCatalog
>
(
res
);
return
res
;
}
...
...
@@ -406,19 +384,6 @@ MergeList & Context::getMergeList() { return shared->merge_list; }
const
MergeList
&
Context
::
getMergeList
()
const
{
return
shared
->
merge_list
;
}
const
Databases
Context
::
getDatabases
()
const
{
auto
lock
=
getLock
();
return
shared
->
databases
;
}
Databases
Context
::
getDatabases
()
{
auto
lock
=
getLock
();
return
shared
->
databases
;
}
Context
::
SessionKey
Context
::
getSessionKey
(
const
String
&
session_id
)
const
{
auto
&
user_name
=
client_info
.
current_user
;
...
...
@@ -526,50 +491,66 @@ std::chrono::steady_clock::duration Context::closeSessions() const
return
shared
->
close_interval
;
}
DatabaseCatalog
&
Context
::
getDatabaseCatalog
()
const
{
return
*
shared
->
database_catalog
;
}
Databases
Context
::
getDatabases
()
const
{
return
shared
->
database_catalog
->
getDatabases
();
}
static
String
resolveDatabase
(
const
String
&
database_name
,
const
String
&
current_database
)
String
Context
::
resolveDatabase
(
const
String
&
database_name
)
const
{
String
res
=
database_name
.
empty
()
?
getCurrentDatabase
()
:
database_name
;
if
(
res
.
empty
())
throw
Exception
(
"Default database is not selected"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
return
res
;
}
String
Context
::
resolveDatabaseAndCheckAccess
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
res
=
database_name
.
empty
()
?
current_database
:
database_name
;
if
(
res
.
empty
())
throw
Exception
(
"Default database is not selected"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
return
res
;
}
//StorageID Context::resolveDatabase(StorageID table_id) const
//{
// table_id.database_name = resolveDatabase(table_id.database_name);
// return table_id;
//}
const
DatabasePtr
Context
::
getDatabase
(
const
String
&
database_name
)
const
DatabasePtr
Context
::
getDatabase
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
assertDatabaseExists
(
db
);
return
shared
->
databases
[
db
];
auto
db
=
resolveDatabaseAndCheckAccess
(
database_name
);
return
shared
->
database_catalog
->
getDatabase
(
db
,
*
this
);
}
DatabasePtr
Context
::
getDatabase
(
const
String
&
database_name
)
DatabasePtr
Context
::
tryGetDatabase
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
assertDatabaseExists
(
db
);
return
shared
->
databases
[
db
];
String
db
=
resolveDatabase
(
database_name
);
return
shared
->
database_catalog
->
tryGetDatabase
(
database_name
,
*
this
);
}
const
DatabasePtr
Context
::
tryGetDatabase
(
const
String
&
database_name
)
const
bool
Context
::
isDatabaseExist
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
auto
it
=
shared
->
databases
.
find
(
db
);
if
(
it
==
shared
->
databases
.
end
())
return
{};
return
it
->
second
;
String
db
=
resolveDatabaseAndCheckAccess
(
database_name
);
return
shared
->
database_catalog
->
isDatabaseExist
(
database_name
);
}
DatabasePtr
Context
::
tryGetDatabase
(
const
String
&
database_nam
e
)
void
Context
::
addDatabase
(
const
String
&
database_name
,
const
DatabasePtr
&
databas
e
)
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
auto
it
=
shared
->
databases
.
find
(
db
);
if
(
it
==
shared
->
databases
.
end
())
return
{};
return
it
->
second
;
shared
->
database_catalog
->
attachDatabase
(
database_name
,
database
,
*
this
);
}
DatabasePtr
Context
::
detachDatabase
(
const
String
&
database_name
)
{
return
shared
->
database_catalog
->
detachDatabase
(
database_name
,
*
this
);
}
String
Context
::
getPath
()
const
...
...
@@ -850,26 +831,17 @@ Dependencies Context::getDependencies(const StorageID & from) const
bool
Context
::
isTableExist
(
const
String
&
database_name
,
const
String
&
table_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
Databases
::
const_iterator
it
=
shared
->
databases
.
find
(
db
);
return
shared
->
databases
.
end
()
!=
it
&&
it
->
second
->
isTableExist
(
*
this
,
table_name
);
//FIXME do we need resolve temporary tables here?
auto
table_id
=
resolveStorageID
({
database_name
,
table_name
});
return
shared
->
database_catalog
->
isTableExist
(
table_id
,
*
this
);
}
bool
Context
::
isDictionaryExists
(
const
String
&
database_name
,
const
String
&
dictionary_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
Databases
::
const_iterator
it
=
shared
->
databases
.
find
(
db
);
return
shared
->
databases
.
end
()
!=
it
&&
it
->
second
->
isDictionaryExist
(
*
this
,
dictionary_name
);
}
bool
Context
::
isDatabaseExist
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
return
shared
->
databases
.
end
()
!=
shared
->
databases
.
find
(
db
);
String
db
=
resolveDatabaseAndCheckAccess
(
database_name
);
auto
db_ptr
=
shared
->
database_catalog
->
tryGetDatabase
(
database_name
,
*
this
);
return
db_ptr
&&
db_ptr
->
isDictionaryExist
(
*
this
,
dictionary_name
);
}
bool
Context
::
isExternalTableExist
(
const
String
&
table_name
)
const
...
...
@@ -880,32 +852,18 @@ bool Context::isExternalTableExist(const String & table_name) const
void
Context
::
assertTableDoesntExist
(
const
String
&
database_name
,
const
String
&
table_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
Databases
::
const_iterator
it
=
shared
->
databases
.
find
(
db
);
if
(
shared
->
databases
.
end
()
!=
it
&&
it
->
second
->
isTableExist
(
*
this
,
table_name
))
throw
Exception
(
"Table "
+
backQuoteIfNeed
(
db
)
+
"."
+
backQuoteIfNeed
(
table_name
)
+
" already exists."
,
ErrorCodes
::
TABLE_ALREADY_EXISTS
);
//FIXME do we need resolve temporary tables here? (and do we need this method?)
auto
table_id
=
resolveStorageID
({
database_name
,
table_name
});
shared
->
database_catalog
->
assertTableDoesntExist
(
table_id
,
*
this
);
}
void
Context
::
assertDatabaseExists
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
if
(
shared
->
databases
.
end
()
==
shared
->
databases
.
find
(
db
))
throw
Exception
(
"Database "
+
backQuoteIfNeed
(
db
)
+
" doesn't exist"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
String
db
=
resolveDatabaseAndCheckAccess
(
database_name
);
shared
->
database_catalog
->
assertDatabaseExists
(
db
);
}
void
Context
::
assertDatabaseDoesntExist
(
const
String
&
database_name
)
const
{
auto
lock
=
getLock
();
String
db
=
resolveDatabase
(
database_name
,
current_database
);
if
(
shared
->
databases
.
end
()
!=
shared
->
databases
.
find
(
db
))
throw
Exception
(
"Database "
+
backQuoteIfNeed
(
db
)
+
" already exists."
,
ErrorCodes
::
DATABASE_ALREADY_EXISTS
);
}
const
Scalars
&
Context
::
getScalars
()
const
{
return
scalars
;
...
...
@@ -979,41 +937,8 @@ StoragePtr Context::tryGetTable(const StorageID & table_id) const
StoragePtr
Context
::
getTableImpl
(
const
StorageID
&
table_id
,
std
::
optional
<
Exception
>
*
exception
)
const
{
String
db
;
DatabasePtr
database
;
{
auto
lock
=
getLock
();
if
(
table_id
.
database_name
.
empty
())
{
StoragePtr
res
=
tryGetExternalTable
(
table_id
.
table_name
);
if
(
res
)
return
res
;
}
db
=
resolveDatabase
(
table_id
.
database_name
,
current_database
);
Databases
::
const_iterator
it
=
shared
->
databases
.
find
(
db
);
if
(
shared
->
databases
.
end
()
==
it
)
{
if
(
exception
)
exception
->
emplace
(
"Database "
+
backQuoteIfNeed
(
db
)
+
" doesn't exist"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
return
{};
}
database
=
it
->
second
;
}
auto
table
=
database
->
tryGetTable
(
*
this
,
table_id
.
table_name
);
if
(
!
table
)
{
if
(
exception
)
exception
->
emplace
(
"Table "
+
table_id
.
getNameForLogs
()
+
" doesn't exist."
,
ErrorCodes
::
UNKNOWN_TABLE
);
return
{};
}
return
table
;
auto
resolved_id
=
resolveStorageID
(
table_id
);
return
shared
->
database_catalog
->
getTable
(
resolved_id
,
*
this
,
exception
);
}
...
...
@@ -1023,7 +948,8 @@ void Context::addExternalTable(const String & table_name, const StoragePtr & sto
if
(
external_tables_mapping
.
end
()
!=
external_tables_mapping
.
find
(
table_name
))
throw
Exception
(
"Temporary table "
+
backQuoteIfNeed
(
table_name
)
+
" already exists."
,
ErrorCodes
::
TABLE_ALREADY_EXISTS
);
external_tables_mapping
.
emplace
(
table_name
,
std
::
make_shared
<
TemporaryTableHolder
>
(
*
this
,
shared
->
temporary_and_external_tables
,
storage
,
ast
));
auto
holder
=
std
::
make_shared
<
TemporaryTableHolder
>
(
*
this
,
*
shared
->
database_catalog
->
getDatabaseForTemporaryTables
(),
storage
,
ast
);
external_tables_mapping
.
emplace
(
table_name
,
std
::
move
(
holder
));
}
...
...
@@ -1106,33 +1032,13 @@ std::unique_ptr<DDLGuard> Context::getDDLGuard(const String & database, const St
return
std
::
make_unique
<
DDLGuard
>
(
shared
->
ddl_guards
[
database
],
std
::
move
(
lock
),
table
);
}
void
Context
::
addDatabase
(
const
String
&
database_name
,
const
DatabasePtr
&
database
)
{
auto
lock
=
getLock
();
assertDatabaseDoesntExist
(
database_name
);
shared
->
databases
[
database_name
]
=
database
;
}
DatabasePtr
Context
::
detachDatabase
(
const
String
&
database_name
)
{
auto
lock
=
getLock
();
auto
res
=
getDatabase
(
database_name
);
shared
->
databases
.
erase
(
database_name
);
return
res
;
}
ASTPtr
Context
::
getCreateExternalTableQuery
(
const
String
&
table_name
)
const
{
auto
it
=
external_tables_mapping
.
find
(
table_name
);
if
(
external_tables_mapping
.
end
()
==
it
)
throw
Exception
(
"Temporary table "
+
backQuoteIfNeed
(
table_name
)
+
" doesn't exist"
,
ErrorCodes
::
UNKNOWN_TABLE
);
return
shared
->
temporary_and_external_tables
.
getCreateTableQuery
(
*
this
,
it
->
second
->
getGlobalTableID
().
table_name
);
return
shared
->
database_catalog
->
getDatabaseForTemporaryTables
()
->
getCreateTableQuery
(
*
this
,
it
->
second
->
getGlobalTableID
().
table_name
);
}
Settings
Context
::
getSettings
()
const
...
...
@@ -1215,6 +1121,7 @@ void Context::checkSettingsConstraints(const SettingsChanges & changes)
String
Context
::
getCurrentDatabase
()
const
{
auto
lock
=
getLock
();
return
current_database
;
}
...
...
@@ -2211,6 +2118,12 @@ void Context::resetInputCallbacks()
input_blocks_reader
=
{};
}
StorageID
Context
::
resolveStorageID
(
StorageID
storage_id
)
const
{
auto
lock
=
getLock
();
return
resolveStorageIDUnlocked
(
std
::
move
(
storage_id
));
}
StorageID
Context
::
resolveStorageIDUnlocked
(
StorageID
storage_id
)
const
{
if
(
storage_id
.
uuid
!=
UUIDHelpers
::
Nil
)
...
...
@@ -2228,7 +2141,6 @@ StorageID Context::resolveStorageIDUnlocked(StorageID storage_id) const
throw
Exception
(
"Default database is not selected"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
storage_id
.
database_name
=
current_database
;
}
checkDatabaseAccessRightsImpl
(
storage_id
.
database_name
);
return
storage_id
;
}
...
...
dbms/src/Interpreters/Context.h
浏览文件 @
4ff7bf78
...
...
@@ -144,6 +144,8 @@ struct SubscriptionForUserChange
};
struct
TemporaryTableHolder
;
class
DatabaseCatalog
;
using
DatabaseCatalogPtr
=
std
::
shared_ptr
<
DatabaseCatalog
>
;
/** A set of known objects that can be used in the query.
* Consists of a shared part (always common to all sessions and queries)
...
...
@@ -300,6 +302,8 @@ public:
void
addDependencyUnsafe
(
const
StorageID
&
from
,
const
StorageID
&
where
);
void
removeDependencyUnsafe
(
const
StorageID
&
from
,
const
StorageID
&
where
);
DatabaseCatalog
&
getDatabaseCatalog
()
const
;
/// Checking the existence of the table/database. Database can be empty - in this case the current database is used.
bool
isTableExist
(
const
String
&
database_name
,
const
String
&
table_name
)
const
;
bool
isDatabaseExist
(
const
String
&
database_name
)
const
;
...
...
@@ -307,7 +311,12 @@ public:
bool
isExternalTableExist
(
const
String
&
table_name
)
const
;
void
assertTableDoesntExist
(
const
String
&
database_name
,
const
String
&
table_name
)
const
;
void
assertDatabaseExists
(
const
String
&
database_name
)
const
;
void
assertDatabaseDoesntExist
(
const
String
&
database_name
)
const
;
String
resolveDatabase
(
const
String
&
database_name
)
const
;
String
resolveDatabaseAndCheckAccess
(
const
String
&
database_name
)
const
;
//StorageID resolveDatabase(StorageID table_id) const;
StorageID
resolveStorageID
(
StorageID
storage_id
)
const
;
StorageID
resolveStorageIDUnlocked
(
StorageID
storage_id
)
const
;
const
Scalars
&
getScalars
()
const
;
const
Block
&
getScalar
(
const
String
&
name
)
const
;
...
...
@@ -321,7 +330,6 @@ public:
void
addScalar
(
const
String
&
name
,
const
Block
&
block
);
bool
hasScalar
(
const
String
&
name
)
const
;
bool
removeExternalTable
(
const
String
&
table_name
);
StorageID
resolveStorageIDUnlocked
(
StorageID
storage_id
)
const
;
StoragePtr
executeTableFunction
(
const
ASTPtr
&
table_expression
);
...
...
@@ -410,13 +418,10 @@ public:
/// Get query for the CREATE table.
ASTPtr
getCreateExternalTableQuery
(
const
String
&
table_name
)
const
;
const
DatabasePtr
getDatabase
(
const
String
&
database_name
)
const
;
DatabasePtr
getDatabase
(
const
String
&
database_name
);
const
DatabasePtr
tryGetDatabase
(
const
String
&
database_name
)
const
;
DatabasePtr
tryGetDatabase
(
const
String
&
database_name
);
DatabasePtr
getDatabase
(
const
String
&
database_name
)
const
;
DatabasePtr
tryGetDatabase
(
const
String
&
database_name
)
const
;
const
Databases
getDatabases
()
const
;
Databases
getDatabases
();
Databases
getDatabases
()
const
;
std
::
shared_ptr
<
Context
>
acquireSession
(
const
String
&
session_id
,
std
::
chrono
::
steady_clock
::
duration
timeout
,
bool
session_check
)
const
;
void
releaseSession
(
const
String
&
session_id
,
std
::
chrono
::
steady_clock
::
duration
timeout
);
...
...
@@ -617,12 +622,6 @@ private:
void
calculateUserSettings
();
void
calculateAccessRights
();
/** Check if the current client has access to the specified database.
* If access is denied, throw an exception.
* NOTE: This method should always be called when the `shared->mutex` mutex is acquired.
*/
void
checkDatabaseAccessRightsImpl
(
const
std
::
string
&
database_name
)
const
;
template
<
typename
...
Args
>
void
checkAccessImpl
(
const
Args
&
...
args
)
const
;
...
...
dbms/src/Interpreters/DatabaseCatalog.cpp
0 → 100644
浏览文件 @
4ff7bf78
#include <Interpreters/DatabaseCatalog.h>
#include <Interpreters/Context.h>
#include <Interpreters/loadMetadata.h>
#include <IO/WriteHelpers.h>
#include <Storages/StorageID.h>
#include <Databases/IDatabase.h>
#include <Databases/DatabaseMemory.h>
namespace
DB
{
namespace
ErrorCodes
{
extern
const
int
UNKNOWN_DATABASE
;
extern
const
int
UNKNOWN_TABLE
;
extern
const
int
TABLE_ALREADY_EXISTS
;
extern
const
int
DATABASE_ALREADY_EXISTS
;
}
void
DatabaseCatalog
::
loadDatabases
()
{
auto
db_for_temporary_and_external_tables
=
std
::
make_shared
<
DatabaseMemory
>
(
TEMPORARY_DATABASE
);
attachDatabase
(
TEMPORARY_DATABASE
,
db_for_temporary_and_external_tables
,
global_context
);
}
void
DatabaseCatalog
::
shutdown
()
{
/** At this point, some tables may have threads that block our mutex.
* To shutdown them correctly, we will copy the current list of tables,
* and ask them all to finish their work.
* Then delete all objects with tables.
*/
Databases
current_databases
;
{
std
::
lock_guard
lock
(
databases_mutex
);
current_databases
=
databases
;
}
/// We still hold "databases" (instead of std::move) for Buffer tables to flush data correctly.
for
(
auto
&
database
:
current_databases
)
database
.
second
->
shutdown
();
std
::
lock_guard
lock
(
databases_mutex
);
databases
.
clear
();
for
(
auto
&
elem
:
uuid_map
)
{
std
::
lock_guard
map_lock
(
elem
.
mutex
);
elem
.
map
.
clear
();
}
}
DatabaseAndTable
DatabaseCatalog
::
tryGetByUUID
(
const
UUID
&
uuid
)
const
{
assert
(
uuid
!=
UUIDHelpers
::
Nil
&&
0
<=
getFirstLevelIdx
(
uuid
)
&&
getFirstLevelIdx
(
uuid
)
<
uuid_map
.
size
());
const
UUIDToStorageMapPart
&
map_part
=
uuid_map
[
getFirstLevelIdx
(
uuid
)];
std
::
lock_guard
lock
{
map_part
.
mutex
};
auto
it
=
map_part
.
map
.
find
(
uuid
);
if
(
it
==
map_part
.
map
.
end
())
return
{};
return
it
->
second
;
}
//String DatabaseCatalog::resolveDatabase(const String & database_name, const String & current_database)
//{
// String res = database_name.empty() ? current_database : database_name;
// if (res.empty())
// throw Exception("Default database is not selected", ErrorCodes::UNKNOWN_DATABASE);
// return res;
//}
StoragePtr
DatabaseCatalog
::
getTable
(
const
StorageID
&
table_id
,
const
Context
&
local_context
,
std
::
optional
<
Exception
>
*
exception
)
const
{
//if (table_id.hasUUID())
//{
// auto db_and_table = tryGetByUUID(table_id.uuid);
// if (!db_and_table.first || !db_and_table.second)
// {
// assert(!db_and_table.first && !db_and_table.second);
// if (exception)
// exception->emplace("Table " + table_id.getNameForLogs() + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
// return {};
//
// }
// return db_and_table.second;
//}
std
::
lock_guard
_lock
{
databases_mutex
};
auto
it
=
databases
.
find
(
table_id
.
getDatabaseName
());
if
(
databases
.
end
()
==
it
)
{
if
(
exception
)
exception
->
emplace
(
"Database "
+
backQuoteIfNeed
(
table_id
.
getDatabaseName
())
+
" doesn't exist"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
return
{};
}
auto
database
=
it
->
second
;
auto
table
=
database
->
tryGetTable
(
local_context
,
table_id
.
table_name
);
if
(
!
table
&&
exception
)
exception
->
emplace
(
"Table "
+
table_id
.
getNameForLogs
()
+
" doesn't exist."
,
ErrorCodes
::
UNKNOWN_TABLE
);
return
table
;
}
void
DatabaseCatalog
::
assertDatabaseExists
(
const
String
&
database_name
)
const
{
std
::
lock_guard
lock
{
databases_mutex
};
assertDatabaseExistsUnlocked
(
database_name
);
}
void
DatabaseCatalog
::
assertDatabaseDoesntExist
(
const
String
&
database_name
)
const
{
std
::
lock_guard
lock
{
databases_mutex
};
assertDatabaseDoesntExistUnlocked
(
database_name
);
}
void
DatabaseCatalog
::
assertDatabaseExistsUnlocked
(
const
String
&
database_name
)
const
{
if
(
databases
.
end
()
==
databases
.
find
(
database_name
))
throw
Exception
(
"Database "
+
backQuoteIfNeed
(
database_name
)
+
" doesn't exist"
,
ErrorCodes
::
UNKNOWN_DATABASE
);
}
void
DatabaseCatalog
::
assertDatabaseDoesntExistUnlocked
(
const
String
&
database_name
)
const
{
if
(
databases
.
end
()
!=
databases
.
find
(
database_name
))
throw
Exception
(
"Database "
+
backQuoteIfNeed
(
database_name
)
+
" already exists."
,
ErrorCodes
::
DATABASE_ALREADY_EXISTS
);
}
void
DatabaseCatalog
::
attachDatabase
(
const
String
&
database_name
,
const
DatabasePtr
&
database
,
const
Context
&
/*local_context*/
)
{
//local_context.checkDatabaseAccessRights(database_name);
std
::
lock_guard
lock
{
databases_mutex
};
assertDatabaseDoesntExistUnlocked
(
database_name
);
databases
[
database_name
]
=
database
;
}
DatabasePtr
DatabaseCatalog
::
detachDatabase
(
const
String
&
database_name
,
const
Context
&
local_context
)
{
//local_context.checkDatabaseAccessRights(database_name);
std
::
lock_guard
lock
{
databases_mutex
};
auto
res
=
getDatabase
(
database_name
,
local_context
);
//FIXME locks order
databases
.
erase
(
database_name
);
return
res
;
}
DatabasePtr
DatabaseCatalog
::
getDatabase
(
const
String
&
database_name
,
const
Context
&
/*local_context*/
)
const
{
//String db = local_context.resolveDatabase(database_name);
//local_context.checkDatabaseAccessRights(db); //FIXME non-atomic
std
::
lock_guard
lock
{
databases_mutex
};
assertDatabaseExistsUnlocked
(
database_name
);
return
databases
.
find
(
database_name
)
->
second
;
}
DatabasePtr
DatabaseCatalog
::
tryGetDatabase
(
const
String
&
database_name
,
const
Context
&
/*local_context*/
)
const
{
//String db = local_context.resolveDatabase(database_name);
std
::
lock_guard
lock
{
databases_mutex
};
auto
it
=
databases
.
find
(
database_name
);
if
(
it
==
databases
.
end
())
return
{};
return
it
->
second
;
}
bool
DatabaseCatalog
::
isDatabaseExist
(
const
String
&
database_name
)
const
{
std
::
lock_guard
lock
{
databases_mutex
};
return
databases
.
end
()
!=
databases
.
find
(
database_name
);
}
Databases
DatabaseCatalog
::
getDatabases
()
const
{
std
::
lock_guard
lock
{
databases_mutex
};
return
databases
;
}
bool
DatabaseCatalog
::
isTableExist
(
const
DB
::
StorageID
&
table_id
,
const
DB
::
Context
&
context
)
const
{
//if (table_id.hasUUID())
// return tryGetByUUID(table_id.uuid).second != nullptr;
//else
//{
std
::
lock_guard
lock
{
databases_mutex
};
auto
db
=
databases
.
find
(
table_id
.
database_name
);
return
db
!=
databases
.
end
()
&&
db
->
second
->
isTableExist
(
context
,
table_id
.
table_name
);
//}
}
void
DatabaseCatalog
::
assertTableDoesntExist
(
const
StorageID
&
table_id
,
const
Context
&
context
)
const
{
if
(
!
isTableExist
(
table_id
,
context
))
throw
Exception
(
"Table "
+
table_id
.
getNameForLogs
()
+
" already exists."
,
ErrorCodes
::
TABLE_ALREADY_EXISTS
);
}
DatabasePtr
DatabaseCatalog
::
getDatabaseForTemporaryTables
()
const
{
return
getDatabase
(
TEMPORARY_DATABASE
,
global_context
);
}
void
DatabaseCatalog
::
addUUIDMapping
(
const
UUID
&
uuid
,
DatabasePtr
database
,
StoragePtr
table
)
{
assert
(
uuid
!=
UUIDHelpers
::
Nil
&&
0
<=
getFirstLevelIdx
(
uuid
)
&&
getFirstLevelIdx
(
uuid
)
<
uuid_map
.
size
());
UUIDToStorageMapPart
&
map_part
=
uuid_map
[
getFirstLevelIdx
(
uuid
)];
std
::
lock_guard
lock
{
map_part
.
mutex
};
auto
[
_
,
inserted
]
=
map_part
.
map
.
try_emplace
(
uuid
,
std
::
move
(
database
),
std
::
move
(
table
));
if
(
!
inserted
)
throw
Exception
(
"Mapping for table with UUID="
+
toString
(
uuid
)
+
" already exists"
,
ErrorCodes
::
LOGICAL_ERROR
);
}
void
DatabaseCatalog
::
removeUUIDMapping
(
const
UUID
&
uuid
)
{
assert
(
uuid
!=
UUIDHelpers
::
Nil
&&
0
<=
getFirstLevelIdx
(
uuid
)
&&
getFirstLevelIdx
(
uuid
)
<
uuid_map
.
size
());
UUIDToStorageMapPart
&
map_part
=
uuid_map
[
getFirstLevelIdx
(
uuid
)];
std
::
lock_guard
lock
{
map_part
.
mutex
};
if
(
!
map_part
.
map
.
erase
(
uuid
))
throw
Exception
(
"Mapping for table with UUID="
+
toString
(
uuid
)
+
" doesn't exist"
,
ErrorCodes
::
LOGICAL_ERROR
);
}
}
dbms/src/Interpreters/DatabaseCatalog.h
0 → 100644
浏览文件 @
4ff7bf78
#pragma once
#include <Storages/IStorage_fwd.h>
#include <Core/UUID.h>
#include <boost/noncopyable.hpp>
#include <memory>
#include <map>
#include <unordered_map>
#include <mutex>
#include <array>
namespace
DB
{
class
Context
;
class
IDatabase
;
struct
StorageID
;
class
Exception
;
using
DatabasePtr
=
std
::
shared_ptr
<
IDatabase
>
;
using
DatabaseAndTable
=
std
::
pair
<
DatabasePtr
,
StoragePtr
>
;
//TODO make singleton?
class
DatabaseCatalog
:
boost
::
noncopyable
{
public:
using
Databases
=
std
::
map
<
String
,
std
::
shared_ptr
<
IDatabase
>>
;
static
constexpr
const
char
*
TEMPORARY_DATABASE
=
"_temporary_and_external_tables"
;
static
constexpr
const
char
*
SYSTEM_DATABASE
=
"system"
;
DatabaseCatalog
(
Context
&
global_context_
/*, String default_database_*/
)
:
global_context
(
global_context_
)
/*, default_database(std::move(default_database_))*/
{}
void
loadDatabases
();
void
shutdown
();
//static String resolveDatabase(const String & database_name, const String & current_database);
void
assertDatabaseExists
(
const
String
&
database_name
)
const
;
void
assertDatabaseDoesntExist
(
const
String
&
database_name
)
const
;
DatabasePtr
getDatabaseForTemporaryTables
()
const
;
void
attachDatabase
(
const
String
&
database_name
,
const
DatabasePtr
&
database
,
const
Context
&
local_context
);
// ca, a
DatabasePtr
detachDatabase
(
const
String
&
database_name
,
const
Context
&
local_context
);
// (sr), ca, a
DatabasePtr
getDatabase
(
const
String
&
database_name
,
const
Context
&
local_context
)
const
;
// sr, ca, a
DatabasePtr
tryGetDatabase
(
const
String
&
database_name
,
const
Context
&
local_context
)
const
;
// sr
bool
isDatabaseExist
(
const
String
&
database_name
)
const
;
// sr, ca
Databases
getDatabases
()
const
;
DatabaseAndTable
tryGetByUUID
(
const
UUID
&
uuid
)
const
;
void
assertTableDoesntExist
(
const
StorageID
&
table_id
,
const
Context
&
context
)
const
;
// sr, ca
bool
isTableExist
(
const
StorageID
&
table_id
,
const
Context
&
context
)
const
;
// sr, ca
void
addUUIDMapping
(
const
UUID
&
uuid
,
DatabasePtr
database
,
StoragePtr
table
);
void
removeUUIDMapping
(
const
UUID
&
uuid
);
StoragePtr
getTable
(
const
StorageID
&
table_id
,
const
Context
&
local_context
,
std
::
optional
<
Exception
>
*
exception
)
const
;
private:
void
assertDatabaseExistsUnlocked
(
const
String
&
database_name
)
const
;
void
assertDatabaseDoesntExistUnlocked
(
const
String
&
database_name
)
const
;
struct
UUIDToStorageMapPart
{
std
::
unordered_map
<
UUID
,
DatabaseAndTable
>
map
;
mutable
std
::
mutex
mutex
;
};
static
constexpr
UInt64
bits_for_first_level
=
8
;
using
UUIDToStorageMap
=
std
::
array
<
UUIDToStorageMapPart
,
1ull
<<
bits_for_first_level
>
;
inline
size_t
getFirstLevelIdx
(
const
UUID
&
uuid
)
const
{
return
uuid
.
toUnderType
().
low
>>
(
64
-
bits_for_first_level
);
}
private:
[[
maybe_unused
]]
Context
&
global_context
;
mutable
std
::
mutex
databases_mutex
;
//const String default_database;
Databases
databases
;
UUIDToStorageMap
uuid_map
;
};
}
dbms/src/Interpreters/InterpreterShowTablesQuery.cpp
浏览文件 @
4ff7bf78
...
...
@@ -2,6 +2,7 @@
#include <Parsers/ASTShowTablesQuery.h>
#include <Parsers/formatAST.h>
#include <Interpreters/Context.h>
#include <Interpreters/DatabaseCatalog.h>
#include <Interpreters/executeQuery.h>
#include <Interpreters/InterpreterShowTablesQuery.h>
#include <Common/typeid_cast.h>
...
...
@@ -36,7 +37,7 @@ String InterpreterShowTablesQuery::getRewrittenQuery()
throw
Exception
(
"The `FROM` and `TEMPORARY` cannot be used together in `SHOW TABLES`"
,
ErrorCodes
::
SYNTAX_ERROR
);
String
database
=
query
.
from
.
empty
()
?
context
.
getCurrentDatabase
()
:
query
.
from
;
context
.
assertDatabaseExists
(
database
);
context
.
getDatabaseCatalog
().
assertDatabaseExists
(
database
);
std
::
stringstream
rewritten_query
;
rewritten_query
<<
"SELECT name FROM system."
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录