Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
d43e7a89
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,发现更多精彩内容 >>
提交
d43e7a89
编写于
4月 19, 2019
作者:
V
Vitaly Baranov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement `max` constraints for number settings.
上级
8277e9d8
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
169 addition
and
37 deletion
+169
-37
dbms/src/Common/ErrorCodes.cpp
dbms/src/Common/ErrorCodes.cpp
+1
-0
dbms/src/Core/Settings.cpp
dbms/src/Core/Settings.cpp
+2
-0
dbms/src/Interpreters/Context.cpp
dbms/src/Interpreters/Context.cpp
+13
-5
dbms/src/Interpreters/Context.h
dbms/src/Interpreters/Context.h
+4
-0
dbms/src/Interpreters/SettingsConstraints.cpp
dbms/src/Interpreters/SettingsConstraints.cpp
+100
-29
dbms/src/Interpreters/SettingsConstraints.h
dbms/src/Interpreters/SettingsConstraints.h
+49
-3
未找到文件。
dbms/src/Common/ErrorCodes.cpp
浏览文件 @
d43e7a89
...
...
@@ -426,6 +426,7 @@ namespace ErrorCodes
extern
const
int
BROTLI_WRITE_FAILED
=
449
;
extern
const
int
BAD_TTL_EXPRESSION
=
450
;
extern
const
int
BAD_TTL_FILE
=
451
;
extern
const
int
SETTING_CONSTRAINT_VIOLATION
=
452
;
extern
const
int
KEEPER_EXCEPTION
=
999
;
extern
const
int
POCO_EXCEPTION
=
1000
;
...
...
dbms/src/Core/Settings.cpp
浏览文件 @
d43e7a89
...
...
@@ -34,6 +34,8 @@ void Settings::setProfile(const String & profile_name, const Poco::Util::Abstrac
for
(
const
std
::
string
&
key
:
config_keys
)
{
if
(
key
==
"constraints"
)
continue
;
if
(
key
==
"profile"
)
/// Inheritance of one profile from another.
setProfile
(
config
.
getString
(
elem
+
"."
+
key
),
config
);
else
...
...
dbms/src/Interpreters/Context.cpp
浏览文件 @
d43e7a89
...
...
@@ -620,14 +620,22 @@ void Context::calculateUserSettings()
/// NOTE: we ignore global_context settings (from which it is usually copied)
/// NOTE: global_context settings are immutable and not auto updated
settings
=
Settings
();
settings_constraints
=
SettingsConstraints
();
/// 2) Apply settings from default profile
auto
default_profile_name
=
getDefaultProfileName
();
if
(
profile
!=
default_profile_name
)
set
tings
.
setProfile
(
default_profile_name
,
*
shared
->
users_config
);
set
Profile
(
default_profile_name
);
/// 3) Apply settings from current user
setProfile
(
profile
);
}
void
Context
::
setProfile
(
const
String
&
profile
)
{
settings
.
setProfile
(
profile
,
*
shared
->
users_config
);
settings_constraints
.
setProfile
(
profile
,
*
shared
->
users_config
);
}
...
...
@@ -1033,7 +1041,7 @@ void Context::setSetting(const String & name, const String & value)
auto
lock
=
getLock
();
if
(
name
==
"profile"
)
{
set
tings
.
setProfile
(
value
,
*
shared
->
users_config
);
set
Profile
(
value
);
return
;
}
settings
.
set
(
name
,
value
);
...
...
@@ -1045,7 +1053,7 @@ void Context::setSetting(const String & name, const Field & value)
auto
lock
=
getLock
();
if
(
name
==
"profile"
)
{
set
tings
.
setProfile
(
value
.
safeGet
<
String
>
(),
*
shared
->
users_config
);
set
Profile
(
value
.
safeGet
<
String
>
()
);
return
;
}
settings
.
set
(
name
,
value
);
...
...
@@ -1068,13 +1076,13 @@ void Context::applySettingsChanges(const SettingsChanges & changes)
void
Context
::
checkSettingsConstraints
(
const
SettingChange
&
change
)
{
SettingsConstraints
::
check
(
settings
,
change
);
settings_constraints
.
check
(
settings
,
change
);
}
void
Context
::
checkSettingsConstraints
(
const
SettingsChanges
&
changes
)
{
SettingsConstraints
::
check
(
settings
,
changes
);
settings_constraints
.
check
(
settings
,
changes
);
}
...
...
dbms/src/Interpreters/Context.h
浏览文件 @
d43e7a89
...
...
@@ -4,6 +4,7 @@
#include <Core/NamesAndTypes.h>
#include <Core/Types.h>
#include <Interpreters/ClientInfo.h>
#include <Interpreters/SettingsConstraints.h>
#include <Core/Settings.h>
#include <Parsers/IAST_fwd.h>
#include <Common/LRUCache.h>
...
...
@@ -125,6 +126,7 @@ private:
std
::
shared_ptr
<
QuotaForIntervals
>
quota
;
/// Current quota. By default - empty quota, that have no limits.
String
current_database
;
Settings
settings
;
/// Setting for query execution.
SettingsConstraints
settings_constraints
;
using
ProgressCallback
=
std
::
function
<
void
(
const
Progress
&
progress
)
>
;
ProgressCallback
progress_callback
;
/// Callback for tracking progress of query execution.
QueryStatus
*
process_list_elem
=
nullptr
;
/// For tracking total resource usage for query.
...
...
@@ -484,6 +486,8 @@ private:
*/
void
checkDatabaseAccessRightsImpl
(
const
std
::
string
&
database_name
)
const
;
void
setProfile
(
const
String
&
profile
);
EmbeddedDictionaries
&
getEmbeddedDictionariesImpl
(
bool
throw_on_error
)
const
;
ExternalDictionaries
&
getExternalDictionariesImpl
(
bool
throw_on_error
)
const
;
ExternalModels
&
getExternalModelsImpl
(
bool
throw_on_error
)
const
;
...
...
dbms/src/Interpreters/SettingsConstraints.cpp
浏览文件 @
d43e7a89
#include <Interpreters/SettingsConstraints.h>
#include <Core/Settings.h>
#include <Common/FieldVisitors.h>
#include <IO/WriteHelpers.h>
#include <Poco/Util/AbstractConfiguration.h>
namespace
DB
...
...
@@ -9,43 +12,35 @@ namespace ErrorCodes
extern
const
int
READONLY
;
extern
const
int
QUERY_IS_PROHIBITED
;
extern
const
int
NO_ELEMENTS_IN_CONFIG
;
extern
const
int
SETTING_CONSTRAINT_VIOLATION
;
}
namespace
{
thread_local
Settings
temp_settings
;
}
void
checkImpl
(
const
Settings
&
current_settings
,
size_t
index
)
{
const
auto
&
new_setting
=
temp_settings
[
index
];
Field
new_value
=
new_setting
.
getValue
();
const
auto
&
current_setting
=
current_settings
[
index
];
Field
current_value
=
current_setting
.
getValue
();
/// Setting isn't checked if value wasn't changed.
if
(
current_value
==
new_value
)
return
;
const
StringRef
&
name
=
new_setting
.
getName
();
if
(
!
current_settings
.
allow_ddl
&&
name
==
"allow_ddl"
)
throw
Exception
(
"Cannot modify 'allow_ddl' setting when DDL queries are prohibited for the user"
,
ErrorCodes
::
QUERY_IS_PROHIBITED
);
/** The `readonly` value is understood as follows:
* 0 - everything allowed.
* 1 - only read queries can be made; you can not change the settings.
* 2 - You can only do read queries and you can change the settings, except for the `readonly` setting.
*/
if
(
current_settings
.
readonly
==
1
)
throw
Exception
(
"Cannot modify '"
+
name
.
toString
()
+
"' setting in readonly mode"
,
ErrorCodes
::
READONLY
);
if
(
current_settings
.
readonly
>
1
&&
name
==
"readonly"
)
throw
Exception
(
"Cannot modify 'readonly' setting in readonly mode"
,
ErrorCodes
::
READONLY
);
}
SettingsConstraints
::
SettingsConstraints
()
=
default
;
SettingsConstraints
::
SettingsConstraints
(
const
SettingsConstraints
&
src
)
=
default
;
SettingsConstraints
&
SettingsConstraints
::
operator
=
(
const
SettingsConstraints
&
src
)
=
default
;
SettingsConstraints
::
SettingsConstraints
(
SettingsConstraints
&&
src
)
=
default
;
SettingsConstraints
&
SettingsConstraints
::
operator
=
(
SettingsConstraints
&&
src
)
=
default
;
SettingsConstraints
::~
SettingsConstraints
()
=
default
;
void
SettingsConstraints
::
setMaxValue
(
const
String
&
name
,
const
String
&
max_value
)
{
max_settings
.
set
(
name
,
max_value
);
}
void
SettingsConstraints
::
setMaxValue
(
const
String
&
name
,
const
Field
&
max_value
)
{
max_settings
.
set
(
name
,
max_value
);
}
void
SettingsConstraints
::
check
(
const
Settings
&
current_settings
,
const
SettingChange
&
change
)
void
SettingsConstraints
::
check
(
const
Settings
&
current_settings
,
const
SettingChange
&
change
)
const
{
size_t
index
=
current_settings
.
find
(
change
.
name
);
if
(
index
==
Settings
::
npos
)
...
...
@@ -56,10 +51,86 @@ void SettingsConstraints::check(const Settings & current_settings, const Setting
}
void
SettingsConstraints
::
check
(
const
Settings
&
current_settings
,
const
SettingsChanges
&
changes
)
void
SettingsConstraints
::
check
(
const
Settings
&
current_settings
,
const
SettingsChanges
&
changes
)
const
{
for
(
const
auto
&
change
:
changes
)
check
(
current_settings
,
change
);
}
void
SettingsConstraints
::
checkImpl
(
const
Settings
&
current_settings
,
size_t
index
)
const
{
const
auto
&
new_setting
=
temp_settings
[
index
];
Field
new_value
=
new_setting
.
getValue
();
const
auto
&
current_setting
=
current_settings
[
index
];
Field
current_value
=
current_setting
.
getValue
();
/// Setting isn't checked if value wasn't changed.
if
(
current_value
==
new_value
)
return
;
const
StringRef
&
name
=
new_setting
.
getName
();
if
(
!
current_settings
.
allow_ddl
&&
name
==
"allow_ddl"
)
throw
Exception
(
"Cannot modify 'allow_ddl' setting when DDL queries are prohibited for the user"
,
ErrorCodes
::
QUERY_IS_PROHIBITED
);
/** The `readonly` value is understood as follows:
* 0 - everything allowed.
* 1 - only read queries can be made; you can not change the settings.
* 2 - You can only do read queries and you can change the settings, except for the `readonly` setting.
*/
if
(
current_settings
.
readonly
==
1
)
throw
Exception
(
"Cannot modify '"
+
name
.
toString
()
+
"' setting in readonly mode"
,
ErrorCodes
::
READONLY
);
if
(
current_settings
.
readonly
>
1
&&
name
==
"readonly"
)
throw
Exception
(
"Cannot modify 'readonly' setting in readonly mode"
,
ErrorCodes
::
READONLY
);
const
auto
&
max_setting
=
max_settings
[
index
];
if
(
max_setting
.
isChanged
())
{
Field
max_value
=
max_setting
.
getValue
();
if
(
new_value
>
max_value
)
throw
Exception
(
"Setting "
+
name
.
toString
()
+
" shouldn't be greater than "
+
applyVisitor
(
FieldVisitorToString
(),
max_value
),
ErrorCodes
::
SETTING_CONSTRAINT_VIOLATION
);
}
}
void
SettingsConstraints
::
setProfile
(
const
String
&
profile_name
,
const
Poco
::
Util
::
AbstractConfiguration
&
config
)
{
String
parent_profile
=
"profiles."
+
profile_name
+
".profile"
;
if
(
config
.
has
(
parent_profile
))
setProfile
(
parent_profile
,
config
);
// Inheritance of one profile from another.
String
path_to_constraints
=
"profiles."
+
profile_name
+
".constraints"
;
if
(
config
.
has
(
path_to_constraints
))
loadFromConfig
(
path_to_constraints
,
config
);
}
void
SettingsConstraints
::
loadFromConfig
(
const
String
&
path_to_constraints
,
const
Poco
::
Util
::
AbstractConfiguration
&
config
)
{
if
(
!
config
.
has
(
path_to_constraints
))
throw
Exception
(
"There is no path '"
+
path_to_constraints
+
"' in configuration file."
,
ErrorCodes
::
NO_ELEMENTS_IN_CONFIG
);
Poco
::
Util
::
AbstractConfiguration
::
Keys
names
;
config
.
keys
(
path_to_constraints
,
names
);
for
(
const
String
&
name
:
names
)
{
String
path_to_name
=
path_to_constraints
+
"."
+
name
;
Poco
::
Util
::
AbstractConfiguration
::
Keys
constraint_types
;
config
.
keys
(
path_to_name
,
constraint_types
);
for
(
const
String
&
constraint_type
:
constraint_types
)
{
String
path_to_type
=
path_to_name
+
"."
+
constraint_type
;
if
(
constraint_type
==
"max"
)
setMaxValue
(
name
,
config
.
getString
(
path_to_type
));
else
throw
Exception
(
"Setting "
+
constraint_type
+
" value for "
+
name
+
" isn't supported"
,
ErrorCodes
::
NOT_IMPLEMENTED
);
}
}
}
}
dbms/src/Interpreters/SettingsConstraints.h
浏览文件 @
d43e7a89
#pragma once
#include <Common/SettingsChanges.h>
#include <Core/Settings.h>
namespace
Poco
{
namespace
Util
{
class
AbstractConfiguration
;
}
}
namespace
DB
{
...
...
@@ -8,7 +18,20 @@ struct Settings;
/** Checks if specified changes of settings are allowed or not.
* If the changes are not allowed (i.e. violates some constraints) this class throws an exception.
* This class checks that we are not in the read-only mode.
* The constraints are set by editing the `users.xml` file.
* For examples, the following lines in `users.xml` will set that `max_memory_usage` cannot be greater than 20000000000:
* <profiles>
* <user_profile>
* <max_memory_usage>10000000000</max_memory_usage>
* ...
* <constraints>
* <max_memory_usage>
* <max>20000000000</max>
* </max_memory_usage>
* </constraints>
* </user_profile>
* </profiles>
* This class also checks that we are not in the read-only mode.
* If a setting cannot be change due to the read-only mode this class throws an exception.
* The value of `readonly` value is understood as follows:
* 0 - everything allowed.
...
...
@@ -18,8 +41,31 @@ struct Settings;
class
SettingsConstraints
{
public:
static
void
check
(
const
Settings
&
current_settings
,
const
SettingChange
&
change
);
static
void
check
(
const
Settings
&
current_settings
,
const
SettingsChanges
&
changes
);
SettingsConstraints
();
SettingsConstraints
(
const
SettingsConstraints
&
src
);
SettingsConstraints
&
operator
=
(
const
SettingsConstraints
&
src
);
SettingsConstraints
(
SettingsConstraints
&&
src
);
SettingsConstraints
&
operator
=
(
SettingsConstraints
&&
src
);
~
SettingsConstraints
();
void
setMaxValue
(
const
String
&
name
,
const
String
&
max_value
);
void
setMaxValue
(
const
String
&
name
,
const
Field
&
max_value
);
void
check
(
const
Settings
&
current_settings
,
const
SettingChange
&
change
)
const
;
void
check
(
const
Settings
&
current_settings
,
const
SettingsChanges
&
changes
)
const
;
/** Set multiple settings from "profile" (in server configuration file (users.xml), profiles contain groups of multiple settings).
* The profile can also be set using the `set` functions, like the profile setting.
*/
void
setProfile
(
const
String
&
profile_name
,
const
Poco
::
Util
::
AbstractConfiguration
&
config
);
/// Loads the constraints from configuration file, at "path" prefix in configuration.
void
loadFromConfig
(
const
String
&
path
,
const
Poco
::
Util
::
AbstractConfiguration
&
config
);
private:
void
checkImpl
(
const
Settings
&
current_settings
,
size_t
index
)
const
;
Settings
max_settings
;
};
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录