Compare commits

...

8 Commits

Author SHA1 Message Date
pufit
98eca16f6d
Merge 396544a70d into 4e56c026cd 2024-11-20 12:55:57 -05:00
pufit
396544a70d fix tests 2024-11-20 02:41:35 -05:00
pufit
0f1cf3a3b8 fix parser 2024-11-20 01:37:54 -05:00
pufit
ebb19cd9b5 fix tests 2024-11-20 01:25:11 -05:00
pufit
026aa8b2ee fix keyword 2024-11-18 14:03:28 -08:00
pufit
7d64f4f3d5 fix conflicts 2024-11-18 13:59:24 -08:00
pufit
97866c71b7 Merge branch 'master' into add-syntax-alter-user-modify-settings
# Conflicts:
#	docs/en/sql-reference/statements/alter/role.md
#	docs/en/sql-reference/statements/alter/settings-profile.md
#	docs/ru/sql-reference/statements/alter/role.md
#	docs/ru/sql-reference/statements/alter/settings-profile.md
#	src/Access/SettingsProfileElement.cpp
#	src/Access/SettingsProfileElement.h
#	src/Interpreters/Context.cpp
#	src/Interpreters/Context.h
#	src/Parsers/Access/ASTCreateUserQuery.cpp
#	src/Parsers/Access/ParserCreateRoleQuery.cpp
#	src/Parsers/Access/ParserCreateSettingsProfileQuery.cpp
#	src/Parsers/Access/ParserCreateUserQuery.cpp
#	src/Parsers/Access/ParserSettingsProfileElement.cpp
#	tests/queries/0_stateless/01294_create_settings_profile.reference
2024-11-18 13:13:27 -08:00
Vitaly Baranov
7357bc7114 Add syntax ALTER USER {ADD|MODIFY|DROP SETTING}, ALTER USER {ADD|DROP PROFILE}, the same for ALTER ROLE and ALTER PROFILE. 2023-12-22 15:31:19 +01:00
42 changed files with 1390 additions and 190 deletions

View File

@ -13,5 +13,10 @@ Syntax:
``` sql
ALTER ROLE [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[ON CLUSTER cluster_name]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```

View File

@ -13,6 +13,11 @@ Syntax:
``` sql
ALTER SETTINGS PROFILE [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[ON CLUSTER cluster_name]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | INHERIT 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | INHERIT 'profile_name'] [,...]
[TO {{role1 | user1 [, role2 | user2 ...]} | NONE | ALL | ALL EXCEPT {role1 | user1 [, role2 | user2 ...]}}]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```

View File

@ -18,7 +18,12 @@ ALTER USER [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[VALID UNTIL datetime]
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
[GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE|CONST|CHANGEABLE_IN_READONLY] [,...] ]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```
To use `ALTER USER` you must have the [ALTER USER](../../../sql-reference/statements/grant.md#access-management) privilege.

View File

@ -13,5 +13,10 @@ sidebar_label: ROLE
``` sql
ALTER ROLE [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[ON CLUSTER cluster_name]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```

View File

@ -13,6 +13,11 @@ sidebar_label: SETTINGS PROFILE
``` sql
ALTER SETTINGS PROFILE [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[ON CLUSTER cluster_name]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | INHERIT 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | INHERIT 'profile_name'] [,...]
[TO {{role1 | user1 [, role2 | user2 ...]} | NONE | ALL | ALL EXCEPT {role1 | user1 [, role2 | user2 ...]}}]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```

View File

@ -19,7 +19,12 @@ ALTER USER [IF EXISTS] name1 [RENAME TO new_name |, name2 [,...]]
[VALID UNTIL datetime]
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
[GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
[ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE|CONST|CHANGEABLE_IN_READONLY] [,...] ]
[DROP SETTINGS variable [,...] ]
[ADD PROFILES 'profile_name' [,...] ]
[DROP PROFILES 'profile_name' [,...] ]
[DROP ALL PROFILES]
[DROP ALL SETTINGS]
```
Для выполнения `ALTER USER` необходима привилегия [ALTER USER](../grant.md#grant-access-management).

View File

@ -45,7 +45,7 @@ namespace
roles_info.names_of_roles[role_id] = role->getName();
roles_info.access.makeUnion(role->access);
roles_info.settings_from_enabled_roles.merge(role->settings);
roles_info.settings_from_enabled_roles.merge(role->settings, /* normalize= */ false);
for (const auto & granted_role : role->granted_roles.getGranted())
collectRoles(roles_info, skip_ids, get_role_function, granted_role, false, false);

View File

@ -137,6 +137,13 @@ void SettingsConstraints::merge(const SettingsConstraints & other)
}
void SettingsConstraints::check(const Settings & current_settings, const AlterSettingsProfileElements & profile_elements, SettingSource source) const
{
check(current_settings, profile_elements.add_settings, source);
check(current_settings, profile_elements.modify_settings, source);
/// We don't check `drop_settings` here.
}
void SettingsConstraints::check(const Settings & current_settings, const SettingsProfileElements & profile_elements, SettingSource source) const
{
for (const auto & element : profile_elements)

View File

@ -74,10 +74,11 @@ public:
void merge(const SettingsConstraints & other);
/// Checks whether `change` violates these constraints and throws an exception if so.
void check(const Settings & current_settings, const SettingsProfileElements & profile_elements, SettingSource source) const;
void check(const Settings & current_settings, const SettingChange & change, SettingSource source) const;
void check(const Settings & current_settings, const SettingsChanges & changes, SettingSource source) const;
void check(const Settings & current_settings, SettingsChanges & changes, SettingSource source) const;
void check(const Settings & current_settings, const SettingsProfileElements & profile_elements, SettingSource source) const;
void check(const Settings & current_settings, const AlterSettingsProfileElements & profile_elements, SettingSource source) const;
/// Checks whether `change` violates these constraints and throws an exception if so. (setting short name is expected inside `changes`)
void check(const MergeTreeSettings & current_settings, const SettingChange & change) const;

View File

@ -9,6 +9,8 @@
#include <IO/WriteHelpers.h>
#include <Parsers/Access/ASTSettingsProfileElement.h>
#include <base/removeDuplicates.h>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
namespace DB
@ -19,6 +21,7 @@ namespace ErrorCodes
extern const int NOT_IMPLEMENTED;
}
SettingsProfileElement::SettingsProfileElement(const ASTSettingsProfileElement & ast)
{
init(ast, nullptr);
@ -116,16 +119,20 @@ std::shared_ptr<ASTSettingsProfileElement> SettingsProfileElement::toASTWithName
}
SettingsProfileElements::SettingsProfileElements(const ASTSettingsProfileElements & ast)
SettingsProfileElements::SettingsProfileElements(const ASTSettingsProfileElements & ast, bool normalize_)
{
for (const auto & ast_element : ast.elements)
emplace_back(*ast_element);
if (normalize_)
normalize();
}
SettingsProfileElements::SettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control)
SettingsProfileElements::SettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control, bool normalize_)
{
for (const auto & ast_element : ast.elements)
emplace_back(*ast_element, access_control);
if (normalize_)
normalize();
}
@ -133,7 +140,11 @@ std::shared_ptr<ASTSettingsProfileElements> SettingsProfileElements::toAST() con
{
auto res = std::make_shared<ASTSettingsProfileElements>();
for (const auto & element : *this)
res->elements.push_back(element.toAST());
{
auto element_ast = element.toAST();
if (!element_ast->empty())
res->elements.push_back(element_ast);
}
return res;
}
@ -141,7 +152,11 @@ std::shared_ptr<ASTSettingsProfileElements> SettingsProfileElements::toASTWithNa
{
auto res = std::make_shared<ASTSettingsProfileElements>();
for (const auto & element : *this)
res->elements.push_back(element.toASTWithNames(access_control));
{
auto element_ast = element.toASTWithNames(access_control);
if (!element_ast->empty())
res->elements.push_back(element_ast);
}
return res;
}
@ -220,9 +235,11 @@ void SettingsProfileElements::removeSettingsKeepProfiles()
}
void SettingsProfileElements::merge(const SettingsProfileElements & other)
void SettingsProfileElements::merge(const SettingsProfileElements & other, bool normalize_)
{
insert(end(), other.begin(), other.end());
if (normalize_)
normalize();
}
@ -280,6 +297,81 @@ std::vector<UUID> SettingsProfileElements::toProfileIDs() const
return res;
}
void SettingsProfileElements::normalize()
{
/// Ensure that each element represents either a setting or a profile.
{
SettingsProfileElements new_elements;
for (auto & element : *this)
{
if (element.parent_profile && !element.setting_name.empty())
{
SettingsProfileElement new_element;
new_element.parent_profile = element.parent_profile;
element.parent_profile.reset();
new_elements.push_back(std::move(new_element));
}
}
insert(end(), new_elements.begin(), new_elements.end());
}
/// Partitioning: first profiles, then settings.
/// We use std::stable_partition() here because we want to preserve the relative order of profiles and the relative order of settings.
/// (We need that order to be preserved to remove duplicates correctly - see below.)
auto profiles_begin = begin();
auto profiles_end = std::stable_partition(begin(), end(), [](const SettingsProfileElement & element) { return static_cast<bool>(element.parent_profile); });
auto settings_begin = profiles_end;
auto settings_end = end();
/// Remove duplicates among profiles.
/// We keep the last position of any used profile.
/// It's important to keep exactly the last position (and not just any position) because profiles can override settings from each other.
/// For example, [pr_A, pr_B, pr_A, pr_C] is always the same as [pr_B, pr_A, pr_C], but can be not the same as [pr_A, pr_B, pr_C]
/// if pr_A and pr_B give different values to same settings.
{
boost::container::flat_set<UUID> profile_ids;
profile_ids.reserve(profiles_end - profiles_begin);
auto it = profiles_end;
while (it != profiles_begin)
{
--it;
auto & element = *it;
if (element.parent_profile && !profile_ids.emplace(*element.parent_profile).second)
element.parent_profile.reset();
}
}
/// Remove duplicates among settings.
/// We keep the first position of any used setting, and merge settings with the same name to that first element.
{
boost::container::flat_map<std::string_view, SettingsProfileElements::iterator> setting_name_to_first_encounter;
setting_name_to_first_encounter.reserve(settings_end - settings_begin);
for (auto it = settings_begin; it != settings_end; ++it)
{
auto & element = *it;
auto first = setting_name_to_first_encounter.emplace(element.setting_name, it).first->second;
if (it != first)
{
auto & first_element = *first;
if (element.value)
first_element.value = element.value;
if (element.min_value)
first_element.min_value = element.min_value;
if (element.max_value)
first_element.max_value = element.max_value;
if (element.writability)
first_element.writability = element.writability;
element.setting_name.clear();
}
}
}
/// Remove empty elements.
std::erase_if(*this, [](const SettingsProfileElement & element) { return element.empty(); });
}
bool SettingsProfileElements::isBackupAllowed() const
{
for (const auto & setting : *this)
@ -296,4 +388,139 @@ bool SettingsProfileElements::isAllowBackupSetting(const String & setting_name)
return Settings::resolveName(setting_name) == ALLOW_BACKUP_SETTING_NAME;
}
AlterSettingsProfileElements::AlterSettingsProfileElements(const SettingsProfileElements & ast)
{
drop_all_settings = true;
drop_all_profiles = true;
add_settings = ast;
}
AlterSettingsProfileElements::AlterSettingsProfileElements(const ASTSettingsProfileElements & ast)
: AlterSettingsProfileElements(SettingsProfileElements{ast})
{
}
AlterSettingsProfileElements::AlterSettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control)
: AlterSettingsProfileElements(SettingsProfileElements{ast, access_control})
{
}
AlterSettingsProfileElements::AlterSettingsProfileElements(const ASTAlterSettingsProfileElements & ast)
{
drop_all_settings = ast.drop_all_settings;
drop_all_profiles = ast.drop_all_profiles;
if (ast.add_settings)
add_settings = SettingsProfileElements{*ast.add_settings, /* normalize= */ false}; /// For "ALTER" the normalization is unnecessary.
if (ast.modify_settings)
modify_settings = SettingsProfileElements{*ast.modify_settings, /* normalize= */ false};
if (ast.drop_settings)
drop_settings = SettingsProfileElements{*ast.drop_settings, /* normalize= */ false};
}
AlterSettingsProfileElements::AlterSettingsProfileElements(const ASTAlterSettingsProfileElements & ast, const AccessControl & access_control)
{
drop_all_settings = ast.drop_all_settings;
drop_all_profiles = ast.drop_all_profiles;
if (ast.add_settings)
add_settings = SettingsProfileElements{*ast.add_settings, access_control, /* normalize= */ false}; /// For "ALTER" the normalization is unnecessary.
if (ast.modify_settings)
modify_settings = SettingsProfileElements{*ast.modify_settings, access_control, /* normalize= */ false};
if (ast.drop_settings)
drop_settings = SettingsProfileElements{*ast.drop_settings, access_control, /* normalize= */ false};
}
void SettingsProfileElements::applyChanges(const AlterSettingsProfileElements & changes)
{
/// Apply "DROP" changes.
if (changes.drop_all_profiles)
{
for (auto & element : *this)
element.parent_profile.reset(); /// We only make this element empty, the element will be removed in normalizeProfileElements().
}
if (changes.drop_all_settings)
{
for (auto & element : *this)
element.setting_name.clear(); /// We only make this element empty, the element will be removed in normalizeProfileElements().
}
auto apply_drop_setting = [&](const String & setting_name)
{
for (auto & element : *this)
{
if (element.setting_name == setting_name)
element.setting_name.clear();
}
};
auto apply_drop_profile = [&](const UUID & profile_id)
{
for (auto & element : *this)
{
if (element.parent_profile == profile_id)
element.parent_profile.reset();
}
};
for (const auto & drop : changes.drop_settings)
{
if (drop.parent_profile)
apply_drop_profile(*drop.parent_profile);
if (!drop.setting_name.empty())
apply_drop_setting(drop.setting_name);
}
auto apply_modify_setting = [&](const SettingsProfileElement & modify)
{
SettingsProfileElement new_element;
new_element.setting_name = modify.setting_name;
new_element.value = modify.value;
new_element.min_value = modify.min_value;
new_element.max_value = modify.max_value;
new_element.writability = modify.writability;
push_back(new_element); /// normalizeProfileElements() will merge this new element with the previous elements.
};
/// Apply "ADD" changes.
auto apply_add_setting = [&](const SettingsProfileElement & add)
{
/// "ADD SETTING" must replace the value and the constraints of a setting, so first we need drop the previous elements for that setting.
apply_drop_setting(add.setting_name);
apply_modify_setting(add);
};
auto apply_add_profile = [&](const UUID & profile_id)
{
SettingsProfileElement new_element;
new_element.parent_profile = profile_id;
push_back(new_element); /// We don't care about possible duplicates here, normalizeProfileElements() will remove duplicates.
};
for (const auto & add : changes.add_settings)
{
if (add.parent_profile)
apply_add_profile(*add.parent_profile);
if (!add.setting_name.empty())
apply_add_setting(add);
}
/// Apply "MODIFY" changes.
for (const auto & modify : changes.modify_settings)
{
chassert(!modify.parent_profile); /// There is no such thing as "MODIFY PROFILE".
if (!modify.setting_name.empty())
apply_modify_setting(modify);
}
/// Remove empty elements and duplicates, and sort the result.
normalize();
}
}

View File

@ -13,8 +13,10 @@ namespace DB
struct Settings;
class SettingsChanges;
class SettingsConstraints;
struct AlterSettingsProfileElements;
class ASTSettingsProfileElement;
class ASTSettingsProfileElements;
class ASTAlterSettingsProfileElements;
class AccessControl;
@ -44,6 +46,8 @@ struct SettingsProfileElement
std::shared_ptr<ASTSettingsProfileElement> toAST() const;
std::shared_ptr<ASTSettingsProfileElement> toASTWithNames(const AccessControl & access_control) const;
bool empty() const { return !parent_profile && (setting_name.empty() || (!value && !min_value && !max_value && !writability)); }
bool isConstraint() const;
private:
@ -57,8 +61,9 @@ public:
SettingsProfileElements() = default;
/// The constructor from AST requires the AccessControl if `ast.id_mode == false`.
SettingsProfileElements(const ASTSettingsProfileElements & ast); /// NOLINT
SettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control);
SettingsProfileElements(const ASTSettingsProfileElements & ast, bool normalize_ = true); /// NOLINT
SettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control, bool normalize_ = true);
std::shared_ptr<ASTSettingsProfileElements> toAST() const;
std::shared_ptr<ASTSettingsProfileElements> toASTWithNames(const AccessControl & access_control) const;
@ -70,16 +75,41 @@ public:
void removeSettingsKeepProfiles();
void merge(const SettingsProfileElements & other);
Settings toSettings() const;
SettingsChanges toSettingsChanges() const;
SettingsConstraints toSettingsConstraints(const AccessControl & access_control) const;
std::vector<UUID> toProfileIDs() const;
bool isBackupAllowed() const;
/// Normalizes this list of profile elements: removes duplicates and empty elements, and also sorts the elements
/// in the following order: first profiles, then settings.
/// The function is called automatically after parsing profile elements from an AST and
/// at the end of an "ALTER PROFILE (USER/ROLE) command".
void normalize();
/// Appends all the elements of another list of profile elements to this list.
void merge(const SettingsProfileElements & other, bool normalize_ = true);
/// Applies changes from an "ALTER PROFILE (USER/ROLE)" command. Always normalizes the result.
void applyChanges(const AlterSettingsProfileElements & changes);
bool isBackupAllowed() const;
static bool isAllowBackupSetting(const String & setting_name);
};
struct AlterSettingsProfileElements
{
bool drop_all_settings = false;
bool drop_all_profiles = false;
SettingsProfileElements add_settings;
SettingsProfileElements modify_settings;
SettingsProfileElements drop_settings;
AlterSettingsProfileElements() = default;
explicit AlterSettingsProfileElements(const SettingsProfileElements & ast);
explicit AlterSettingsProfileElements(const ASTSettingsProfileElements & ast);
explicit AlterSettingsProfileElements(const ASTAlterSettingsProfileElements & ast);
AlterSettingsProfileElements(const ASTSettingsProfileElements & ast, const AccessControl & access_control);
AlterSettingsProfileElements(const ASTAlterSettingsProfileElements & ast, const AccessControl & access_control);
};
}

View File

@ -135,8 +135,8 @@ void SettingsProfilesCache::mergeSettingsAndConstraintsFor(EnabledSettings & ena
merged_settings.emplace_back(new_element);
}
merged_settings.merge(enabled.params.settings_from_enabled_roles);
merged_settings.merge(enabled.params.settings_from_user);
merged_settings.merge(enabled.params.settings_from_enabled_roles, /* normalize= */ false);
merged_settings.merge(enabled.params.settings_from_user, /* normalize= */ false);
auto info = std::make_shared<SettingsProfilesInfo>(access_control);

View File

@ -23,7 +23,7 @@ namespace
Role & role,
const ASTCreateRoleQuery & query,
const String & override_name,
const std::optional<SettingsProfileElements> & override_settings)
const std::optional<AlterSettingsProfileElements> & override_settings)
{
if (!override_name.empty())
role.setName(override_name);
@ -33,9 +33,11 @@ namespace
role.setName(query.names.front());
if (override_settings)
role.settings = *override_settings;
role.settings.applyChanges(*override_settings);
else if (query.alter_settings)
role.settings.applyChanges(AlterSettingsProfileElements{*query.alter_settings});
else if (query.settings)
role.settings = *query.settings;
role.settings.applyChanges(AlterSettingsProfileElements{*query.settings});
}
}
@ -51,14 +53,14 @@ BlockIO InterpreterCreateRoleQuery::execute()
else
getContext()->checkAccess(AccessType::CREATE_ROLE);
std::optional<SettingsProfileElements> settings_from_query;
if (query.settings)
{
settings_from_query = SettingsProfileElements{*query.settings, access_control};
std::optional<AlterSettingsProfileElements> settings_from_query;
if (query.alter_settings)
settings_from_query = AlterSettingsProfileElements{*query.alter_settings, access_control};
else if (query.settings)
settings_from_query = AlterSettingsProfileElements{SettingsProfileElements(*query.settings, access_control)};
if (!query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::ROLE);
}
if (settings_from_query && !query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::ROLE);
if (!query.cluster.empty())
return executeDDLQueryOnCluster(updated_query_ptr, getContext());

View File

@ -25,7 +25,7 @@ namespace
SettingsProfile & profile,
const ASTCreateSettingsProfileQuery & query,
const String & override_name,
const std::optional<SettingsProfileElements> & override_settings,
const std::optional<AlterSettingsProfileElements> & override_settings,
const std::optional<RolesOrUsersSet> & override_to_roles)
{
if (!override_name.empty())
@ -36,9 +36,11 @@ namespace
profile.setName(query.names.front());
if (override_settings)
profile.elements = *override_settings;
profile.elements.applyChanges(*override_settings);
else if (query.alter_settings)
profile.elements.applyChanges(AlterSettingsProfileElements{*query.alter_settings});
else if (query.settings)
profile.elements = *query.settings;
profile.elements.applyChanges(AlterSettingsProfileElements{*query.settings});
if (override_to_roles)
profile.to_roles = *override_to_roles;
@ -59,14 +61,14 @@ BlockIO InterpreterCreateSettingsProfileQuery::execute()
else
getContext()->checkAccess(AccessType::CREATE_SETTINGS_PROFILE);
std::optional<SettingsProfileElements> settings_from_query;
if (query.settings)
{
settings_from_query = SettingsProfileElements{*query.settings, access_control};
std::optional<AlterSettingsProfileElements> settings_from_query;
if (query.alter_settings)
settings_from_query = AlterSettingsProfileElements{*query.alter_settings, access_control};
else if (query.settings)
settings_from_query = AlterSettingsProfileElements{SettingsProfileElements(*query.settings, access_control)};
if (!query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::PROFILE);
}
if (settings_from_query && !query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::PROFILE);
if (!query.cluster.empty())
{

View File

@ -43,7 +43,7 @@ namespace
const std::vector<AuthenticationData> authentication_methods,
const std::shared_ptr<ASTUserNameWithHost> & override_name,
const std::optional<RolesOrUsersSet> & override_default_roles,
const std::optional<SettingsProfileElements> & override_settings,
const std::optional<AlterSettingsProfileElements> & override_settings,
const std::optional<RolesOrUsersSet> & override_grantees,
const std::optional<time_t> & global_valid_until,
bool reset_authentication_methods,
@ -172,9 +172,11 @@ namespace
user.default_database = query.default_database->database_name;
if (override_settings)
user.settings = *override_settings;
user.settings.applyChanges(*override_settings);
else if (query.alter_settings)
user.settings.applyChanges(AlterSettingsProfileElements{*query.alter_settings});
else if (query.settings)
user.settings = *query.settings;
user.settings.applyChanges(AlterSettingsProfileElements{*query.settings});
if (override_grantees)
user.grantees = *override_grantees;
@ -219,14 +221,14 @@ BlockIO InterpreterCreateUserQuery::execute()
}
}
std::optional<SettingsProfileElements> settings_from_query;
if (query.settings)
{
settings_from_query = SettingsProfileElements{*query.settings, access_control};
std::optional<AlterSettingsProfileElements> settings_from_query;
if (query.alter_settings)
settings_from_query = AlterSettingsProfileElements{*query.alter_settings, access_control};
else if (query.settings)
settings_from_query = AlterSettingsProfileElements{*query.settings, access_control};
if (!query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::USER);
}
if (settings_from_query && !query.attach)
getContext()->checkSettingsConstraints(*settings_from_query, SettingSource::USER);
if (!query.cluster.empty())
return executeDDLQueryOnCluster(updated_query_ptr, getContext());

View File

@ -71,10 +71,13 @@ namespace
if (!user.settings.empty())
{
std::shared_ptr<ASTSettingsProfileElements> query_settings;
if (attach_mode)
query->settings = user.settings.toAST();
query_settings = user.settings.toAST();
else
query->settings = user.settings.toASTWithNames(*access_control);
query_settings = user.settings.toASTWithNames(*access_control);
if (!query_settings->empty())
query->settings = query_settings;
}
if (user.grantees != RolesOrUsersSet::AllTag{})
@ -105,10 +108,13 @@ namespace
if (!role.settings.empty())
{
std::shared_ptr<ASTSettingsProfileElements> query_settings;
if (attach_mode)
query->settings = role.settings.toAST();
query_settings = role.settings.toAST();
else
query->settings = role.settings.toASTWithNames(*access_control);
query_settings = role.settings.toASTWithNames(*access_control);
if (!query_settings->empty())
query->settings = query_settings;
}
return query;
@ -123,12 +129,16 @@ namespace
if (!profile.elements.empty())
{
std::shared_ptr<ASTSettingsProfileElements> query_settings;
if (attach_mode)
query->settings = profile.elements.toAST();
query_settings = profile.elements.toAST();
else
query->settings = profile.elements.toASTWithNames(*access_control);
if (query->settings)
query->settings->setUseInheritKeyword(true);
query_settings = profile.elements.toASTWithNames(*access_control);
if (!query_settings->empty())
{
query_settings->setUseInheritKeyword(true);
query->settings = query_settings;
}
}
if (!profile.to_roles.empty())

View File

@ -2521,7 +2521,7 @@ void Context::applySettingsChanges(const SettingsChanges & changes)
applySettingsChangesWithLock(changes, lock);
}
void Context::checkSettingsConstraintsWithLock(const SettingsProfileElements & profile_elements, SettingSource source)
void Context::checkSettingsConstraintsWithLock(const AlterSettingsProfileElements & profile_elements, SettingSource source)
{
getSettingsConstraintsAndCurrentProfilesWithLock()->constraints.check(*settings, profile_elements, source);
if (getApplicationType() == ApplicationType::LOCAL || getApplicationType() == ApplicationType::SERVER)
@ -2561,7 +2561,7 @@ void Context::checkMergeTreeSettingsConstraintsWithLock(const MergeTreeSettings
getSettingsConstraintsAndCurrentProfilesWithLock()->constraints.check(merge_tree_settings, changes);
}
void Context::checkSettingsConstraints(const SettingsProfileElements & profile_elements, SettingSource source)
void Context::checkSettingsConstraints(const AlterSettingsProfileElements & profile_elements, SettingSource source)
{
SharedLockGuard lock(mutex);
checkSettingsConstraintsWithLock(profile_elements, source);

View File

@ -145,7 +145,7 @@ struct Settings;
struct SettingChange;
class SettingsChanges;
struct SettingsConstraintsAndProfileIDs;
class SettingsProfileElements;
struct AlterSettingsProfileElements;
class RemoteHostFilter;
class IDisk;
using DiskPtr = std::shared_ptr<IDisk>;
@ -865,7 +865,7 @@ public:
void applySettingsChanges(const SettingsChanges & changes);
/// Checks the constraints.
void checkSettingsConstraints(const SettingsProfileElements & profile_elements, SettingSource source);
void checkSettingsConstraints(const AlterSettingsProfileElements & profile_elements, SettingSource source);
void checkSettingsConstraints(const SettingChange & change, SettingSource source);
void checkSettingsConstraints(const SettingsChanges & changes, SettingSource source);
void checkSettingsConstraints(SettingsChanges & changes, SettingSource source);
@ -1413,7 +1413,7 @@ private:
void setCurrentDatabaseWithLock(const String & name, const std::lock_guard<ContextSharedMutex> & lock);
void checkSettingsConstraintsWithLock(const SettingsProfileElements & profile_elements, SettingSource source);
void checkSettingsConstraintsWithLock(const AlterSettingsProfileElements & profile_elements, SettingSource source);
void checkSettingsConstraintsWithLock(const SettingChange & change, SettingSource source);
@ -1422,6 +1422,9 @@ private:
void checkSettingsConstraintsWithLock(SettingsChanges & changes, SettingSource source);
void clampToSettingsConstraintsWithLock(SettingsChanges & changes, SettingSource source);
void checkSettingsConstraintsWithLock(const AlterSettingsProfileElements & profile_elements, SettingSource source) const;
void clampToSettingsConstraintsWithLock(SettingsChanges & changes, SettingSource source) const;
void checkMergeTreeSettingsConstraintsWithLock(const MergeTreeSettings & merge_tree_settings, const SettingsChanges & changes) const;

View File

@ -31,6 +31,12 @@ namespace
format.ostr << (format.hilite ? IAST::hilite_keyword : "") << " SETTINGS " << (format.hilite ? IAST::hilite_none : "");
settings.format(format);
}
void formatAlterSettings(const ASTAlterSettingsProfileElements & alter_settings, const IAST::FormatSettings & format)
{
format.ostr << " ";
alter_settings.format(format);
}
}
@ -47,6 +53,9 @@ ASTPtr ASTCreateRoleQuery::clone() const
if (settings)
res->settings = std::static_pointer_cast<ASTSettingsProfileElements>(settings->clone());
if (alter_settings)
res->alter_settings = std::static_pointer_cast<ASTAlterSettingsProfileElements>(alter_settings->clone());
return res;
}
@ -82,7 +91,9 @@ void ASTCreateRoleQuery::formatImpl(const FormatSettings & format, FormatState &
if (!new_name.empty())
formatRenameTo(new_name, format);
if (settings && (!settings->empty() || alter))
if (alter_settings)
formatAlterSettings(*alter_settings, format);
else if (settings)
formatSettings(*settings, format);
}

View File

@ -7,6 +7,7 @@
namespace DB
{
class ASTSettingsProfileElements;
class ASTAlterSettingsProfileElements;
/** CREATE ROLE [IF NOT EXISTS | OR REPLACE] name
@ -14,7 +15,12 @@ class ASTSettingsProfileElements;
*
* ALTER ROLE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
*/
class ASTCreateRoleQuery : public IAST, public ASTQueryWithOnCluster
{
@ -31,6 +37,7 @@ public:
String storage_name;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
String getID(char) const override;
ASTPtr clone() const override;

View File

@ -33,6 +33,12 @@ namespace
settings.format(format);
}
void formatAlterSettings(const ASTAlterSettingsProfileElements & alter_settings, const IAST::FormatSettings & format)
{
format.ostr << " ";
alter_settings.format(format);
}
void formatToRoles(const ASTRolesOrUsersSet & roles, const IAST::FormatSettings & settings)
{
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " TO " << (settings.hilite ? IAST::hilite_none : "");
@ -57,6 +63,9 @@ ASTPtr ASTCreateSettingsProfileQuery::clone() const
if (settings)
res->settings = std::static_pointer_cast<ASTSettingsProfileElements>(settings->clone());
if (alter_settings)
res->alter_settings = std::static_pointer_cast<ASTAlterSettingsProfileElements>(alter_settings->clone());
return res;
}
@ -92,7 +101,9 @@ void ASTCreateSettingsProfileQuery::formatImpl(const FormatSettings & format, Fo
if (!new_name.empty())
formatRenameTo(new_name, format);
if (settings && (!settings->empty() || alter))
if (alter_settings)
formatAlterSettings(*alter_settings, format);
else if (settings)
formatSettings(*settings, format);
if (to_roles && (!to_roles->empty() || alter))

View File

@ -7,6 +7,7 @@
namespace DB
{
class ASTSettingsProfileElements;
class ASTAlterSettingsProfileElements;
class ASTRolesOrUsersSet;
@ -16,7 +17,12 @@ class ASTRolesOrUsersSet;
*
* ALTER SETTINGS PROFILE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
*/
class ASTCreateSettingsProfileQuery : public IAST, public ASTQueryWithOnCluster
@ -34,6 +40,7 @@ public:
String new_name;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
std::shared_ptr<ASTRolesOrUsersSet> to_roles;
@ -44,4 +51,5 @@ public:
ASTPtr getRewrittenASTWithoutOnCluster(const WithoutOnClusterASTRewriteParams &) const override { return removeOnCluster<ASTCreateSettingsProfileQuery>(clone()); }
QueryKind getQueryKind() const override { return QueryKind::Create; }
};
}

View File

@ -149,13 +149,17 @@ namespace
default_roles.format(settings);
}
void formatSettings(const ASTSettingsProfileElements & settings, const IAST::FormatSettings & format)
{
format.ostr << (format.hilite ? IAST::hilite_keyword : "") << " SETTINGS " << (format.hilite ? IAST::hilite_none : "");
settings.format(format);
}
void formatAlterSettings(const ASTAlterSettingsProfileElements & alter_settings, const IAST::FormatSettings & format)
{
format.ostr << " ";
alter_settings.format(format);
}
void formatGrantees(const ASTRolesOrUsersSet & grantees, const IAST::FormatSettings & settings)
{
@ -198,6 +202,9 @@ ASTPtr ASTCreateUserQuery::clone() const
if (settings)
res->settings = std::static_pointer_cast<ASTSettingsProfileElements>(settings->clone());
if (alter_settings)
res->alter_settings = std::static_pointer_cast<ASTAlterSettingsProfileElements>(alter_settings->clone());
for (const auto & authentication_method : authentication_methods)
{
auto ast_clone = std::static_pointer_cast<ASTAuthenticationData>(authentication_method->clone());
@ -278,7 +285,9 @@ void ASTCreateUserQuery::formatImpl(const FormatSettings & format, FormatState &
if (default_roles)
formatDefaultRoles(*default_roles, format);
if (settings && (!settings->empty() || alter))
if (alter_settings)
formatAlterSettings(*alter_settings, format);
else if (settings)
formatSettings(*settings, format);
if (grantees)

View File

@ -13,6 +13,7 @@ class ASTUserNamesWithHost;
class ASTRolesOrUsersSet;
class ASTDatabaseOrNone;
class ASTSettingsProfileElements;
class ASTAlterSettingsProfileElements;
class ASTAuthenticationData;
@ -30,7 +31,12 @@ class ASTAuthenticationData;
* [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
* [DEFAULT DATABASE database | NONE]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*/
class ASTCreateUserQuery : public IAST, public ASTQueryWithOnCluster
@ -58,6 +64,7 @@ public:
std::shared_ptr<ASTRolesOrUsersSet> default_roles;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
std::shared_ptr<ASTRolesOrUsersSet> grantees;
std::shared_ptr<ASTDatabaseOrNone> default_database;

View File

@ -3,6 +3,7 @@
#include <Common/FieldVisitorToString.h>
#include <Common/quoteString.h>
#include <IO/Operators.h>
#include <base/insertAtEnd.h>
namespace DB
@ -21,8 +22,54 @@ namespace
settings.ostr << backQuote(str);
}
}
void formatSettingsProfileElementsForAlter(std::string_view kind, const ASTSettingsProfileElements & elements, const IAST::FormatSettings & settings)
{
bool need_comma = false;
size_t num_profiles = elements.getNumberOfProfiles();
if (num_profiles > 0)
{
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << kind << " " << (num_profiles == 1 ? "PROFILE" : "PROFILES")
<< (settings.hilite ? IAST::hilite_none : "") << " ";
for (const auto & element : elements.elements)
{
if (!element->parent_profile.empty())
{
if (need_comma)
settings.ostr << ", ";
formatProfileNameOrID(element->parent_profile, /* is_id= */ false, settings);
need_comma = true;
}
}
}
size_t num_settings = elements.getNumberOfSettings();
if (num_settings > 0)
{
if (need_comma)
settings.ostr << ", ";
need_comma = false;
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << kind << " " << (num_settings == 1 ? "SETTING" : "SETTINGS")
<< (settings.hilite ? IAST::hilite_none : "") << " ";
for (const auto & element : elements.elements)
{
if (!element->setting_name.empty())
{
if (need_comma)
settings.ostr << ", ";
element->format(settings);
need_comma = true;
}
}
}
}
}
void ASTSettingsProfileElement::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const
{
if (!parent_profile.empty())
@ -82,6 +129,27 @@ bool ASTSettingsProfileElements::empty() const
return true;
}
size_t ASTSettingsProfileElements::getNumberOfSettings() const
{
return std::count_if(elements.begin(), elements.end(), [](const auto & element){ return !element->setting_name.empty(); });
}
size_t ASTSettingsProfileElements::getNumberOfProfiles() const
{
return std::count_if(elements.begin(), elements.end(), [](const auto & element){ return !element->parent_profile.empty(); });
}
ASTPtr ASTSettingsProfileElements::clone() const
{
auto res = std::make_shared<ASTSettingsProfileElements>(*this);
for (auto & element : res->elements)
element = std::static_pointer_cast<ASTSettingsProfileElement>(element->clone());
return res;
}
void ASTSettingsProfileElements::formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const
{
@ -109,4 +177,108 @@ void ASTSettingsProfileElements::setUseInheritKeyword(bool use_inherit_keyword_)
element->use_inherit_keyword = use_inherit_keyword_;
}
void ASTSettingsProfileElements::add(ASTSettingsProfileElements && other)
{
insertAtEnd(elements, std::move(other.elements));
}
String ASTAlterSettingsProfileElements::getID(char) const
{
return "AlterSettingsProfileElements";
}
ASTPtr ASTAlterSettingsProfileElements::clone() const
{
auto res = std::make_shared<ASTAlterSettingsProfileElements>(*this);
if (add_settings)
res->add_settings = std::static_pointer_cast<ASTSettingsProfileElements>(add_settings->clone());
if (modify_settings)
res->modify_settings = std::static_pointer_cast<ASTSettingsProfileElements>(modify_settings->clone());
if (drop_settings)
res->drop_settings = std::static_pointer_cast<ASTSettingsProfileElements>(drop_settings->clone());
return res;
}
void ASTAlterSettingsProfileElements::formatImpl(const FormatSettings & format, FormatState &, FormatStateStacked) const
{
bool need_comma = false;
if (drop_all_settings)
{
format.ostr << (format.hilite ? IAST::hilite_keyword : "") << "DROP ALL SETTINGS" << (format.hilite ? IAST::hilite_none : "");
need_comma = true;
}
if (drop_all_profiles)
{
if (need_comma)
format.ostr << ", ";
format.ostr << (format.hilite ? IAST::hilite_keyword : "") << "DROP ALL PROFILES" << (format.hilite ? IAST::hilite_none : "");
need_comma = true;
}
if (drop_settings && !drop_settings->empty())
{
if (need_comma)
format.ostr << ", ";
formatSettingsProfileElementsForAlter("DROP", *drop_settings, format);
need_comma = true;
}
if (add_settings && !add_settings->empty())
{
if (need_comma)
format.ostr << ", ";
formatSettingsProfileElementsForAlter("ADD", *add_settings, format);
need_comma = true;
}
if (modify_settings && !modify_settings->empty())
{
if (need_comma)
format.ostr << ", ";
formatSettingsProfileElementsForAlter("MODIFY", *modify_settings, format);
}
}
void ASTAlterSettingsProfileElements::add(ASTAlterSettingsProfileElements && other)
{
drop_all_settings |= other.drop_all_settings;
drop_all_profiles |= other.drop_all_profiles;
if (other.add_settings)
{
if (!add_settings)
add_settings = std::make_shared<ASTSettingsProfileElements>();
add_settings->add(std::move(*other.add_settings));
}
if (other.add_settings)
{
if (!add_settings)
add_settings = std::make_shared<ASTSettingsProfileElements>();
add_settings->add(std::move(*other.add_settings));
}
if (other.modify_settings)
{
if (!modify_settings)
modify_settings = std::make_shared<ASTSettingsProfileElements>();
modify_settings->add(std::move(*other.modify_settings));
}
if (other.drop_settings)
{
if (!drop_settings)
drop_settings = std::make_shared<ASTSettingsProfileElements>();
drop_settings->add(std::move(*other.drop_settings));
}
}
}

View File

@ -39,10 +39,41 @@ public:
bool empty() const;
size_t getNumberOfSettings() const;
size_t getNumberOfProfiles() const;
String getID(char) const override { return "SettingsProfileElements"; }
ASTPtr clone() const override { return std::make_shared<ASTSettingsProfileElements>(*this); }
ASTPtr clone() const override;
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override;
void setUseInheritKeyword(bool use_inherit_keyword_);
void add(ASTSettingsProfileElements && other);
};
/* Represents a clause used to alter settings or profiles assigned to a user or a role or another profile.
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
*/
class ASTAlterSettingsProfileElements : public IAST
{
public:
std::shared_ptr<ASTSettingsProfileElements> add_settings;
std::shared_ptr<ASTSettingsProfileElements> modify_settings;
std::shared_ptr<ASTSettingsProfileElements> drop_settings;
bool drop_all_settings = false;
bool drop_all_profiles = false;
String getID(char) const override;
ASTPtr clone() const override;
void formatImpl(const FormatSettings & format, FormatState &, FormatStateStacked) const override;
void add(ASTAlterSettingsProfileElements && other);
};
}

View File

@ -25,20 +25,31 @@ namespace
});
}
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
if (!ParserKeyword{Keyword::SETTINGS}.ignore(pos, expected))
return false;
ASTPtr new_settings_ast;
ASTPtr ast;
ParserSettingsProfileElements elements_p;
elements_p.useIDMode(id_mode);
if (!elements_p.parse(pos, new_settings_ast, expected))
if (!elements_p.parse(pos, ast, expected))
return false;
settings = std::move(new_settings_ast->as<ASTSettingsProfileElements &>().elements);
settings = typeid_cast<std::shared_ptr<ASTSettingsProfileElements>>(ast);
return true;
});
}
bool parseAlterSettings(IParserBase::Pos & pos, Expected & expected, std::shared_ptr<ASTAlterSettingsProfileElements> & alter_settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
ASTPtr ast;
ParserAlterSettingsProfileElements elements_p;
if (!elements_p.parse(pos, ast, expected))
return false;
alter_settings = typeid_cast<std::shared_ptr<ASTAlterSettingsProfileElements>>(ast);
return true;
});
}
@ -91,6 +102,7 @@ bool ParserCreateRoleQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
String new_name;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
String cluster;
String storage_name;
@ -99,14 +111,27 @@ bool ParserCreateRoleQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
if (alter && new_name.empty() && (names.size() == 1) && parseRenameTo(pos, expected, new_name))
continue;
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
if (alter)
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
insertAtEnd(settings->elements, std::move(new_settings));
continue;
std::shared_ptr<ASTAlterSettingsProfileElements> new_alter_settings;
if (parseAlterSettings(pos, expected, new_alter_settings))
{
if (!alter_settings)
alter_settings = std::make_shared<ASTAlterSettingsProfileElements>();
alter_settings->add(std::move(*new_alter_settings));
continue;
}
}
else
{
std::shared_ptr<ASTSettingsProfileElements> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
settings->add(std::move(*new_settings));
continue;
}
}
if (cluster.empty() && parseOnCluster(pos, expected, cluster))
@ -130,6 +155,7 @@ bool ParserCreateRoleQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
query->names = std::move(names);
query->new_name = std::move(new_name);
query->settings = std::move(settings);
query->alter_settings = std::move(alter_settings);
query->storage_name = std::move(storage_name);
return true;

View File

@ -11,7 +11,12 @@ namespace DB
*
* ALTER ROLE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
*/
class ParserCreateRoleQuery : public IParserBase
{

View File

@ -27,20 +27,32 @@ namespace
});
}
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
if (!ParserKeyword{Keyword::SETTINGS}.ignore(pos, expected))
return false;
ASTPtr new_settings_ast;
ASTPtr ast;
ParserSettingsProfileElements elements_p;
elements_p.useInheritKeyword(true).useIDMode(id_mode);
if (!elements_p.parse(pos, new_settings_ast, expected))
if (!elements_p.parse(pos, ast, expected))
return false;
settings = std::move(new_settings_ast->as<ASTSettingsProfileElements &>().elements);
settings = typeid_cast<std::shared_ptr<ASTSettingsProfileElements>>(ast);
return true;
});
}
bool parseAlterSettings(IParserBase::Pos & pos, Expected & expected, std::shared_ptr<ASTAlterSettingsProfileElements> & alter_settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
ASTPtr ast;
ParserAlterSettingsProfileElements elements_p;
elements_p.useInheritKeyword(true);
if (!elements_p.parse(pos, ast, expected))
return false;
alter_settings = typeid_cast<std::shared_ptr<ASTAlterSettingsProfileElements>>(ast);
return true;
});
}
@ -111,6 +123,7 @@ bool ParserCreateSettingsProfileQuery::parseImpl(Pos & pos, ASTPtr & node, Expec
String new_name;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
String cluster;
String storage_name;
@ -119,14 +132,27 @@ bool ParserCreateSettingsProfileQuery::parseImpl(Pos & pos, ASTPtr & node, Expec
if (alter && new_name.empty() && (names.size() == 1) && parseRenameTo(pos, expected, new_name))
continue;
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
if (alter)
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
insertAtEnd(settings->elements, std::move(new_settings));
continue;
std::shared_ptr<ASTAlterSettingsProfileElements> new_alter_settings;
if (parseAlterSettings(pos, expected, new_alter_settings))
{
if (!alter_settings)
alter_settings = std::make_shared<ASTAlterSettingsProfileElements>();
alter_settings->add(std::move(*new_alter_settings));
continue;
}
}
else
{
std::shared_ptr<ASTSettingsProfileElements> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
settings->add(std::move(*new_settings));
continue;
}
}
if (cluster.empty() && parseOnCluster(pos, expected, cluster))
@ -156,6 +182,7 @@ bool ParserCreateSettingsProfileQuery::parseImpl(Pos & pos, ASTPtr & node, Expec
query->names = std::move(names);
query->new_name = std::move(new_name);
query->settings = std::move(settings);
query->alter_settings = std::move(alter_settings);
query->to_roles = std::move(to_roles);
query->storage_name = std::move(storage_name);

View File

@ -11,7 +11,12 @@ namespace DB
*
* ALTER SETTINGS PROFILE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | INHERIT 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
*/
class ParserCreateSettingsProfileQuery : public IParserBase
{

View File

@ -427,20 +427,31 @@ namespace
}
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::vector<std::shared_ptr<ASTSettingsProfileElement>> & settings)
bool parseSettings(IParserBase::Pos & pos, Expected & expected, bool id_mode, std::shared_ptr<ASTSettingsProfileElements> & settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
if (!ParserKeyword{Keyword::SETTINGS}.ignore(pos, expected))
return false;
ASTPtr new_settings_ast;
ASTPtr ast;
ParserSettingsProfileElements elements_p;
elements_p.useIDMode(id_mode);
if (!elements_p.parse(pos, new_settings_ast, expected))
if (!elements_p.parse(pos, ast, expected))
return false;
settings = std::move(new_settings_ast->as<ASTSettingsProfileElements &>().elements);
settings = typeid_cast<std::shared_ptr<ASTSettingsProfileElements>>(ast);
return true;
});
}
bool parseAlterSettings(IParserBase::Pos & pos, Expected & expected, std::shared_ptr<ASTAlterSettingsProfileElements> & alter_settings)
{
return IParserBase::wrapParseImpl(pos, [&]
{
ASTPtr ast;
ParserAlterSettingsProfileElements elements_p;
if (!elements_p.parse(pos, ast, expected))
return false;
alter_settings = typeid_cast<std::shared_ptr<ASTAlterSettingsProfileElements>>(ast);
return true;
});
}
@ -556,6 +567,7 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
std::vector<std::shared_ptr<ASTAuthenticationData>> auth_data;
std::shared_ptr<ASTRolesOrUsersSet> default_roles;
std::shared_ptr<ASTSettingsProfileElements> settings;
std::shared_ptr<ASTAlterSettingsProfileElements> alter_settings;
std::shared_ptr<ASTRolesOrUsersSet> grantees;
std::shared_ptr<ASTDatabaseOrNone> default_database;
ASTPtr global_valid_until;
@ -604,14 +616,27 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
continue;
}
std::vector<std::shared_ptr<ASTSettingsProfileElement>> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
if (alter)
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
insertAtEnd(settings->elements, std::move(new_settings));
continue;
std::shared_ptr<ASTAlterSettingsProfileElements> new_alter_settings;
if (parseAlterSettings(pos, expected, new_alter_settings))
{
if (!alter_settings)
alter_settings = std::make_shared<ASTAlterSettingsProfileElements>();
alter_settings->add(std::move(*new_alter_settings));
continue;
}
}
else
{
std::shared_ptr<ASTSettingsProfileElements> new_settings;
if (parseSettings(pos, expected, attach_mode, new_settings))
{
if (!settings)
settings = std::make_shared<ASTSettingsProfileElements>();
settings->add(std::move(*new_settings));
continue;
}
}
if (!default_roles && parseDefaultRoles(pos, expected, attach_mode, default_roles))
@ -691,6 +716,7 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
query->remove_hosts = std::move(remove_hosts);
query->default_roles = std::move(default_roles);
query->settings = std::move(settings);
query->alter_settings = std::move(alter_settings);
query->grantees = std::move(grantees);
query->default_database = std::move(default_database);
query->global_valid_until = std::move(global_valid_until);

View File

@ -18,7 +18,12 @@ namespace DB
* [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash}] BY {'password'|'hash'}}|{WITH ldap SERVER 'server_name'}|{WITH kerberos [REALM 'realm']}]
* [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] | PROFILE 'profile_name'] [,...]
* [ADD|MODIFY SETTINGS variable [=value] [MIN [=] min_value] [MAX [=] max_value] [CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY] [,...] ]
* [DROP SETTINGS variable [,...] ]
* [ADD PROFILES 'profile_name' [,...] ]
* [DROP PROFILES 'profile_name' [,...] ]
* [DROP ALL PROFILES]
* [DROP ALL SETTINGS]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*/
class ParserCreateUserQuery : public IParserBase

View File

@ -7,27 +7,13 @@
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/parseIdentifierOrStringLiteral.h>
#include <boost/algorithm/string/predicate.hpp>
#include <base/insertAtEnd.h>
namespace DB
{
namespace
{
bool parseProfileKeyword(IParserBase::Pos & pos, Expected & expected, bool use_inherit_keyword)
{
if (ParserKeyword{Keyword::PROFILE}.ignore(pos, expected))
return true;
if (use_inherit_keyword && ParserKeyword{Keyword::INHERIT}.ignore(pos, expected))
{
ParserKeyword{Keyword::PROFILE}.ignore(pos, expected);
return true;
}
return false;
}
bool parseProfileNameOrID(IParserBase::Pos & pos, Expected & expected, bool id_mode, String & res)
{
return IParserBase::wrapParseImpl(pos, [&]
@ -119,6 +105,17 @@ namespace
}
bool parseSettingName(IParserBase::Pos & pos, Expected & expected, String & res)
{
ASTPtr name_ast;
if (!ParserCompoundIdentifier{}.parse(pos, name_ast, expected))
return false;
res = getIdentifierName(name_ast);
return true;
}
bool parseSettingNameWithValueOrConstraints(
IParserBase::Pos & pos,
Expected & expected,
@ -130,11 +127,10 @@ namespace
{
return IParserBase::wrapParseImpl(pos, [&]
{
ASTPtr name_ast;
if (!ParserCompoundIdentifier{}.parse(pos, name_ast, expected))
String res_setting_name;
if (!parseSettingName(pos, expected, res_setting_name))
return false;
String res_setting_name = getIdentifierName(name_ast);
std::optional<Field> res_value;
std::optional<Field> res_min_value;
std::optional<Field> res_max_value;
@ -169,52 +165,112 @@ namespace
}
bool parseSettingsProfileElement(IParserBase::Pos & pos,
Expected & expected,
bool id_mode,
bool use_inherit_keyword,
bool previous_element_was_parent_profile,
std::shared_ptr<ASTSettingsProfileElement> & result)
bool parseSettingsProfileElements(IParserBase::Pos & pos,
Expected & expected,
bool id_mode,
bool use_inherit_keyword,
std::vector<std::shared_ptr<ASTSettingsProfileElement>> & res)
{
return IParserBase::wrapParseImpl(pos, [&]
std::vector<std::shared_ptr<ASTSettingsProfileElement>> elements;
bool found_none = false;
bool expect_profiles = false;
bool expect_settings = false;
auto parse_element = [&]
{
String parent_profile;
String setting_name;
std::optional<Field> value;
std::optional<Field> min_value;
std::optional<Field> max_value;
std::optional<SettingConstraintWritability> writability;
if (ParserKeyword{Keyword::SETTINGS}.ignore(pos, expected) || ParserKeyword{Keyword::SETTING}.ignore(pos, expected))
{
expect_settings = true;
}
bool ok = parseSettingNameWithValueOrConstraints(pos, expected, setting_name, value, min_value, max_value, writability);
bool expect_settings_next = expect_settings;
if (!ok && (parseProfileKeyword(pos, expected, use_inherit_keyword) || previous_element_was_parent_profile))
ok = parseProfileNameOrID(pos, expected, id_mode, parent_profile);
if (ParserKeyword{Keyword::PROFILES}.ignore(pos, expected) || ParserKeyword{Keyword::PROFILE}.ignore(pos, expected))
{
expect_profiles = true;
expect_settings = false;
}
else if (use_inherit_keyword && ParserKeyword{Keyword::INHERIT}.ignore(pos, expected))
{
if (!ParserKeyword{Keyword::PROFILES}.ignore(pos, expected))
ParserKeyword{Keyword::PROFILE}.ignore(pos, expected);
expect_profiles = true;
expect_settings = false;
}
if (!ok)
if (!expect_profiles && !expect_settings)
return false;
result = std::make_shared<ASTSettingsProfileElement>();
result->parent_profile = std::move(parent_profile);
result->setting_name = std::move(setting_name);
result->value = std::move(value);
result->min_value = std::move(min_value);
result->max_value = std::move(max_value);
result->writability = writability;
result->id_mode = id_mode;
result->use_inherit_keyword = use_inherit_keyword;
return true;
});
if (ParserKeyword{Keyword::NONE}.ignore(pos, expected))
{
found_none = true;
expect_settings = expect_settings_next;
return true;
}
if (expect_settings)
{
String setting_name;
std::optional<Field> value;
std::optional<Field> min_value;
std::optional<Field> max_value;
std::optional<SettingConstraintWritability> writability;
if (parseSettingNameWithValueOrConstraints(pos, expected, setting_name, value, min_value, max_value, writability))
{
auto element = std::make_shared<ASTSettingsProfileElement>();
element->setting_name = std::move(setting_name);
element->value = std::move(value);
element->min_value = std::move(min_value);
element->max_value = std::move(max_value);
element->writability = std::move(writability);
elements.push_back(element);
expect_profiles = false;
expect_settings = expect_settings_next;
return true;
}
}
if (expect_profiles)
{
String profile_name;
if (parseProfileNameOrID(pos, expected, id_mode, profile_name))
{
auto element = std::make_shared<ASTSettingsProfileElement>();
element->parent_profile = std::move(profile_name);
element->id_mode = id_mode;
element->use_inherit_keyword = use_inherit_keyword;
elements.push_back(element);
expect_settings = expect_settings_next;
return true;
}
}
return false;
};
if (!ParserList::parseUtil(pos, expected, parse_element, false))
return false;
if (elements.empty() && !found_none)
return false;
res = std::move(elements);
return true;
}
}
bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
std::shared_ptr<ASTSettingsProfileElement> res;
if (!parseSettingsProfileElement(pos, expected, id_mode, use_inherit_keyword, false, res))
std::vector<std::shared_ptr<ASTSettingsProfileElement>> elements;
if (!parseSettingsProfileElements(pos, expected, id_mode, use_inherit_keyword, elements))
return false;
node = res;
if (elements.size() != 1)
return false;
node = elements[0];
return true;
}
@ -222,28 +278,8 @@ bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected
bool ParserSettingsProfileElements::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
std::vector<std::shared_ptr<ASTSettingsProfileElement>> elements;
if (ParserKeyword{Keyword::NONE}.ignore(pos, expected))
{
}
else
{
bool previous_element_was_parent_profile = false;
auto parse_element = [&]
{
std::shared_ptr<ASTSettingsProfileElement> element;
if (!parseSettingsProfileElement(pos, expected, id_mode, use_inherit_keyword, previous_element_was_parent_profile, element))
return false;
elements.push_back(element);
previous_element_was_parent_profile = !element->parent_profile.empty();
return true;
};
if (!ParserList::parseUtil(pos, expected, parse_element, false))
return false;
}
if (!parseSettingsProfileElements(pos, expected, id_mode, use_inherit_keyword, elements))
return false;
auto result = std::make_shared<ASTSettingsProfileElements>();
result->elements = std::move(elements);
@ -251,4 +287,148 @@ bool ParserSettingsProfileElements::parseImpl(Pos & pos, ASTPtr & node, Expected
return true;
}
bool ParserAlterSettingsProfileElements::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
std::vector<std::shared_ptr<ASTSettingsProfileElement>> add_settings;
std::vector<std::shared_ptr<ASTSettingsProfileElement>> modify_settings;
std::vector<std::shared_ptr<ASTSettingsProfileElement>> drop_settings;
bool drop_all_settings = false;
bool drop_all_profiles = false;
std::vector<std::shared_ptr<ASTSettingsProfileElement>> old_style_settings;
if (parseSettingsProfileElements(pos, expected, /* id_mode= */ false, use_inherit_keyword, old_style_settings))
{
/// old style: "SETTINGS ..." replaces all the settings ad profiles.
add_settings = std::move(old_style_settings);
drop_all_settings = true;
drop_all_profiles = true;
}
else
{
/// new style: "MODIFY SETTINGS ..., ADD PROFILES ..., DROP PROFILES ..., DROP SETTINGS ..."
std::string_view action;
std::string_view target;
auto parse_element = [&]
{
if (ParserKeyword{Keyword::ADD}.ignore(pos, expected))
{
action = "ADD";
target = "";
}
else if (ParserKeyword{Keyword::DROP}.ignore(pos, expected))
{
action = "DROP";
target = "";
}
else if (ParserKeyword{Keyword::MODIFY}.ignore(pos, expected))
{
action = "MODIFY";
target = "";
}
if (!action.empty())
{
if (ParserKeyword{Keyword::ALL_PROFILES}.ignore(pos, expected))
target = "ALL PROFILES";
else if (ParserKeyword{Keyword::ALL_SETTINGS}.ignore(pos, expected))
target = "ALL SETTINGS";
else if (ParserKeyword{Keyword::PROFILES}.ignore(pos, expected) || ParserKeyword{Keyword::PROFILE}.ignore(pos, expected))
target = "PROFILES";
else if (ParserKeyword{Keyword::SETTINGS}.ignore(pos, expected) || ParserKeyword{Keyword::SETTING}.ignore(pos, expected))
target = "SETTINGS";
}
if (target.empty())
return false;
if (target == "PROFILES")
{
auto element = std::make_shared<ASTSettingsProfileElement>();
if (!parseProfileNameOrID(pos, expected, /* id_mode= */ false, element->parent_profile))
return false;
if (action == "ADD")
{
add_settings.push_back(element);
return true;
}
if (action == "DROP")
{
drop_settings.push_back(element);
return true;
}
return false;
}
if (target == "SETTINGS")
{
auto element = std::make_shared<ASTSettingsProfileElement>();
if (action == "ADD" || action == "MODIFY")
{
if (!parseSettingNameWithValueOrConstraints(pos, expected, element->setting_name, element->value, element->min_value, element->max_value, element->writability))
return false;
if (action == "ADD")
add_settings.push_back(element);
else
modify_settings.push_back(element);
return true;
}
if (action == "DROP")
{
ASTPtr name_ast;
if (!ParserCompoundIdentifier{}.parse(pos, name_ast, expected))
return false;
element->setting_name = getIdentifierName(name_ast);
drop_settings.push_back(element);
return true;
}
return false;
}
if (action == "DROP" && target == "ALL PROFILES")
{
drop_all_profiles = true;
return true;
}
if (action == "DROP" && target == "ALL SETTINGS")
{
drop_all_settings = true;
return true;
}
return false;
};
if (!ParserList::parseUtil(pos, expected, parse_element, false))
return false;
}
if (add_settings.empty() && modify_settings.empty() && drop_settings.empty() && !drop_all_settings && !drop_all_profiles)
return false;
auto result = std::make_shared<ASTAlterSettingsProfileElements>();
if (!add_settings.empty())
{
result->add_settings = std::make_shared<ASTSettingsProfileElements>();
result->add_settings->elements = std::move(add_settings);
}
if (!modify_settings.empty())
{
result->modify_settings = std::make_shared<ASTSettingsProfileElements>();
result->modify_settings->elements = std::move(modify_settings);
}
if (!drop_settings.empty())
{
result->drop_settings = std::make_shared<ASTSettingsProfileElements>();
result->drop_settings->elements = std::move(drop_settings);
}
result->drop_all_settings = drop_all_settings;
result->drop_all_profiles = drop_all_profiles;
node = result;
return true;
}
}

View File

@ -39,4 +39,18 @@ private:
bool use_inherit_keyword = false;
};
class ParserAlterSettingsProfileElements : public IParserBase
{
public:
ParserAlterSettingsProfileElements & useInheritKeyword(bool use_inherit_keyword_ = true) { use_inherit_keyword = use_inherit_keyword_; return *this; }
protected:
const char * getName() const override { return "AlterSettingsProfileElements"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
private:
bool use_inherit_keyword = false;
};
}

View File

@ -10,22 +10,25 @@ namespace DB
{
#define APPLY_FOR_PARSER_KEYWORDS(MR_MACROS) \
MR_MACROS(ADD, "ADD") \
MR_MACROS(ADD_COLUMN, "ADD COLUMN") \
MR_MACROS(ADD_CONSTRAINT, "ADD CONSTRAINT") \
MR_MACROS(ADD_INDEX, "ADD INDEX") \
MR_MACROS(ADD_PROJECTION, "ADD PROJECTION") \
MR_MACROS(ADD_STATISTICS, "ADD STATISTICS") \
MR_MACROS(ADD, "ADD") \
MR_MACROS(ADMIN_OPTION_FOR, "ADMIN OPTION FOR") \
MR_MACROS(AFTER, "AFTER") \
MR_MACROS(ALGORITHM, "ALGORITHM") \
MR_MACROS(ALIAS, "ALIAS") \
MR_MACROS(ALL, "ALL") \
MR_MACROS(ALL_PROFILES, "ALL PROFILES") \
MR_MACROS(ALL_SETTINGS, "ALL SETTINGS") \
MR_MACROS(ALTER_COLUMN, "ALTER COLUMN") \
MR_MACROS(ALTER_DATABASE, "ALTER DATABASE") \
MR_MACROS(ALTER_LIVE_VIEW, "ALTER LIVE VIEW") \
MR_MACROS(ALTER_POLICY, "ALTER POLICY") \
MR_MACROS(ALTER_PROFILE, "ALTER PROFILE") \
MR_MACROS(ALTER_PROFILES, "ALTER PROFILES") \
MR_MACROS(ALTER_QUOTA, "ALTER QUOTA") \
MR_MACROS(ALTER_ROLE, "ALTER ROLE") \
MR_MACROS(ALTER_ROW_POLICY, "ALTER ROW POLICY") \
@ -380,6 +383,7 @@ namespace DB
MR_MACROS(PRIMARY_KEY, "PRIMARY KEY") \
MR_MACROS(PRIMARY, "PRIMARY") \
MR_MACROS(PROFILE, "PROFILE") \
MR_MACROS(PROFILES, "PROFILES") \
MR_MACROS(PROJECTION, "PROJECTION") \
MR_MACROS(PROTOBUF, "Protobuf") \
MR_MACROS(PULL, "PULL") \
@ -444,7 +448,8 @@ namespace DB
MR_MACROS(SET_ROLE_DEFAULT, "SET ROLE DEFAULT") \
MR_MACROS(SET_ROLE, "SET ROLE") \
MR_MACROS(SET_TRANSACTION_SNAPSHOT, "SET TRANSACTION SNAPSHOT") \
MR_MACROS(SET, "SET") \
MR_MACROS(SET, "SET") \
MR_MACROS(SETTING, "SETTING") \
MR_MACROS(SETTINGS, "SETTINGS") \
MR_MACROS(SHOW_ACCESS, "SHOW ACCESS") \
MR_MACROS(SHOW_CREATE, "SHOW CREATE") \

View File

@ -49,7 +49,7 @@ CREATE SETTINGS PROFILE `s4_01294` TO r1_01294
CREATE SETTINGS PROFILE `s1_01294` SETTINGS readonly = 1
CREATE SETTINGS PROFILE `s2_01294` SETTINGS readonly CONST
CREATE SETTINGS PROFILE `s3_01294` SETTINGS INHERIT `readonly`
CREATE SETTINGS PROFILE `s4_01294` SETTINGS INHERIT `readonly`, INHERIT `readonly`
CREATE SETTINGS PROFILE `s4_01294` SETTINGS INHERIT `readonly`
CREATE SETTINGS PROFILE `s5_01294` SETTINGS INHERIT `readonly`, readonly = 1
CREATE SETTINGS PROFILE `s6_01294` SETTINGS INHERIT `readonly`, readonly CONST
-- system.settings_profiles

View File

@ -0,0 +1,21 @@
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_b`
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_b`, PROFILE `profile_a`, PROFILE `profile_c`
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_d`
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_e`
CREATE USER test_user IDENTIFIED WITH no_password
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS PROFILE `profile_a`
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_b`
CREATE ROLE test_role SETTINGS PROFILE `profile_b`, PROFILE `profile_a`, PROFILE `profile_c`
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_d`
CREATE ROLE test_role SETTINGS PROFILE `profile_e`
CREATE ROLE test_role
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_b`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_b`, INHERIT `profile_a`, INHERIT `profile_c`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_d`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_e`
CREATE SETTINGS PROFILE `test_profile`

View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CURDIR"/../shell_config.sh
test_user="test_user_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_role="test_role_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_profile="test_profile_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_a="profile_a_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_b="profile_b_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_c="profile_c_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_d="profile_d_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_e="profile_e_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_a};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_b};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_c};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_d};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_e};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_a};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_b};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_c};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_d};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_e};"
function show_create()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "SHOW CREATE $type ${name};" | sed -e "s/${name}/test_${type}/g" -e "s/${profile_a}/profile_a/g" -e "s/${profile_b}/profile_b/g" -e "s/${profile_c}/profile_c/g" -e "s/${profile_d}/profile_d/g" -e "s/${profile_e}/profile_e/g"
}
function run_test()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "DROP $type IF EXISTS ${name};"
$CLICKHOUSE_CLIENT -q "CREATE $type ${name};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILE ${profile_a};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILE ${profile_b};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILES ${profile_a}, ${profile_c};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILE ${profile_d} DROP PROFILES ${profile_b}, ${profile_c};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL PROFILES, ADD PROFILE ${profile_e};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL PROFILES;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "DROP $type ${name};"
}
run_test user ${test_user}
run_test role ${test_role}
run_test profile ${test_profile}
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_a};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_b};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_c};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_d};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_e};"

View File

@ -0,0 +1,39 @@
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_a`, custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS PROFILE `profile_b`, PROFILE `profile_a`, custom_x = 321, custom_s = \'str\' CONST
CREATE USER test_user IDENTIFIED WITH no_password
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, PROFILE `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE ROLE test_role SETTINGS PROFILE `profile_a`, custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE ROLE test_role SETTINGS PROFILE `profile_b`, PROFILE `profile_a`, custom_x = 321, custom_s = \'str\' CONST
CREATE ROLE test_role
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, INHERIT `profile_b`, custom_x = 123, custom_y = 56.5, custom_w = \'www\'
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_a`, custom_x = 123, custom_t = 7, custom_s = \'str\'
CREATE SETTINGS PROFILE `test_profile` SETTINGS INHERIT `profile_b`, INHERIT `profile_a`, custom_x = 321, custom_s = \'str\' CONST
CREATE SETTINGS PROFILE `test_profile`

View File

@ -0,0 +1,86 @@
#!/usr/bin/env bash
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CURDIR"/../shell_config.sh
test_user="test_user_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_role="test_role_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_profile="test_profile_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_a="profile_a_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_b="profile_b_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
profile_c="profile_c_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_a};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_b};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE IF EXISTS ${profile_c};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_a};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_b};"
$CLICKHOUSE_CLIENT -q "CREATE PROFILE ${profile_c};"
function show_create()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "SHOW CREATE $type ${name};" | sed -e "s/${name}/test_${type}/g" -e "s/${profile_a}/profile_a/g" -e "s/${profile_b}/profile_b/g" -e "s/${profile_c}/profile_c/g"
}
function run_test()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "DROP $type IF EXISTS ${name};"
$CLICKHOUSE_CLIENT -q "CREATE $type ${name};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTINGS custom_x = 123, custom_y=56.5, custom_w='www', ADD PROFILES ${profile_a}, ${profile_b}"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS, DROP ALL PROFILES"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTINGS custom_x = 123, custom_y=56.5, custom_w='www', PROFILES ${profile_a}, ${profile_b}"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS, ALL PROFILES"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_x = 123, ADD SETTING custom_y=56.5, ADD SETTING custom_w='www', ADD PROFILE ${profile_a}, ADD PROFILE ${profile_b}"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL PROFILES, DROP ALL SETTINGS"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_x = 123 ADD SETTING custom_y=56.5 ADD SETTING custom_w='www' ADD PROFILE ${profile_a} ADD PROFILE ${profile_b}"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS DROP ALL PROFILES"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_x = 123, custom_t = 7, custom_s = 'str'"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILE ${profile_a}"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD PROFILE ${profile_b}, ${profile_a}, DROP SETTING custom_t, MODIFY SETTING custom_s READONLY, custom_x = 321"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS, ALL PROFILES"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "DROP $type ${name};"
}
run_test user ${test_user}
run_test role ${test_role}
run_test profile ${test_profile}
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_a};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_b};"
$CLICKHOUSE_CLIENT -q "DROP PROFILE ${profile_c};"

View File

@ -0,0 +1,42 @@
CREATE USER test_user IDENTIFIED WITH no_password
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_a = 100
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_a = 100, custom_b = 200
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_a = 100, custom_b = 300, custom_c = 400
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 1000
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 2000
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 500 MAX 2000
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 700 MIN 500 MAX 2000
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 800 MIN 150
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_c = 400, custom_d = 500
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_c = 400, custom_d = 500, custom_x = 1, custom_y = 2
CREATE USER test_user IDENTIFIED WITH no_password SETTINGS custom_z = 3
CREATE USER test_user IDENTIFIED WITH no_password
CREATE ROLE test_role
CREATE ROLE test_role SETTINGS custom_a = 100
CREATE ROLE test_role SETTINGS custom_a = 100, custom_b = 200
CREATE ROLE test_role SETTINGS custom_a = 100, custom_b = 300, custom_c = 400
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 1000
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 2000
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 500 MAX 2000
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 700 MIN 500 MAX 2000
CREATE ROLE test_role SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 800 MIN 150
CREATE ROLE test_role SETTINGS custom_c = 400, custom_d = 500
CREATE ROLE test_role SETTINGS custom_c = 400, custom_d = 500, custom_x = 1, custom_y = 2
CREATE ROLE test_role SETTINGS custom_z = 3
CREATE ROLE test_role
CREATE SETTINGS PROFILE `test_profile`
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_a = 100
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_a = 100, custom_b = 200
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_a = 100, custom_b = 300, custom_c = 400
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 1000
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 0 MAX 2000
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 600 MIN 500 MAX 2000
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 700 MIN 500 MAX 2000
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_b = 300, custom_c = 400, custom_d = 500, custom_e = 800 MIN 150
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_c = 400, custom_d = 500
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_c = 400, custom_d = 500, custom_x = 1, custom_y = 2
CREATE SETTINGS PROFILE `test_profile` SETTINGS custom_z = 3
CREATE SETTINGS PROFILE `test_profile`

View File

@ -0,0 +1,73 @@
#!/usr/bin/env bash
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CURDIR"/../shell_config.sh
test_user="test_user_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_role="test_role_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
test_profile="test_profile_02932_${CLICKHOUSE_DATABASE}_$RANDOM"
function show_create()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "SHOW CREATE $type ${name};" | sed "s/${name}/test_${type}/g"
}
function run_test()
{
local type="$1"
local name="$2"
$CLICKHOUSE_CLIENT -q "DROP $type IF EXISTS ${name};"
$CLICKHOUSE_CLIENT -q "CREATE $type ${name};"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_a=100;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_b=200;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTINGS custom_b=300, custom_c=400;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_d=500 DROP SETTING custom_a;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_e=600 MIN 0 MAX 1000;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} MODIFY SETTING custom_e MAX 2000;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} MODIFY SETTING custom_e MIN 500;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} MODIFY SETTING custom_e=700;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} ADD SETTING custom_e=800 MIN 150;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP SETTINGS custom_b, custom_e;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} MODIFY SETTINGS custom_x=1, custom_y=2;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS, ADD SETTING custom_z=3;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "ALTER $type ${name} DROP ALL SETTINGS;"
show_create $type ${name}
$CLICKHOUSE_CLIENT -q "DROP $type ${name};"
}
run_test user ${test_user}
run_test role ${test_role}
run_test profile ${test_profile}