Use "CREATE SETTINGS PROFILE name SETTINGS INHERIT parent" instead of "CREATE SETTINGS PROFILE name SETTINGS PROFILE parent".

This commit is contained in:
Vitaly Baranov 2020-04-08 02:57:14 +03:00
parent a24471233f
commit 36a5b57ac4
11 changed files with 56 additions and 12 deletions

View File

@ -7,6 +7,7 @@
#include <Parsers/ASTCreateSettingsProfileQuery.h>
#include <Parsers/ASTShowCreateAccessEntityQuery.h>
#include <Parsers/ASTExtendedRoleSet.h>
#include <Parsers/ASTSettingsProfileElement.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/formatAST.h>
#include <Parsers/parseQuery.h>
@ -101,6 +102,8 @@ namespace
query->settings = profile.elements.toAST();
else
query->settings = profile.elements.toASTWithNames(*manager);
if (query->settings)
query->settings->setUseInheritKeyword(true);
}
if (!profile.to_roles.empty())

View File

@ -12,10 +12,12 @@ class ASTExtendedRoleSet;
/** CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
*
* ALTER SETTINGS PROFILE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
*/
class ASTCreateSettingsProfileQuery : public IAST, public ASTQueryWithOnCluster
{

View File

@ -25,7 +25,8 @@ void ASTSettingsProfileElement::formatImpl(const FormatSettings & settings, Form
{
if (!parent_profile.empty())
{
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << "PROFILE " << (settings.hilite ? IAST::hilite_none : "");
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << (use_inherit_keyword ? "INHERIT" : "PROFILE") << " "
<< (settings.hilite ? IAST::hilite_none : "");
formatProfileNameOrID(parent_profile, id_mode, settings);
return;
}
@ -85,4 +86,11 @@ void ASTSettingsProfileElements::formatImpl(const FormatSettings & settings, For
}
}
void ASTSettingsProfileElements::setUseInheritKeyword(bool use_inherit_keyword_)
{
for (auto & element : elements)
element->use_inherit_keyword = use_inherit_keyword_;
}
}

View File

@ -19,6 +19,7 @@ public:
Field max_value;
std::optional<bool> readonly;
bool id_mode = false; /// If true then `parent_profile` keeps UUID, not a name.
bool use_inherit_keyword = false; /// If true then this element is a part of ASTCreateSettingsProfileQuery.
bool empty() const { return parent_profile.empty() && name.empty(); }
@ -41,5 +42,7 @@ public:
String getID(char) const override { return "SettingsProfileElements"; }
ASTPtr clone() const override { return std::make_shared<ASTSettingsProfileElements>(*this); }
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override;
void setUseInheritKeyword(bool use_inherit_keyword_);
};
}

View File

@ -126,7 +126,7 @@ public:
return parse(pos, node, expected);
}
virtual ~IParser() {}
virtual ~IParser() = default;
};
using ParserPtr = std::unique_ptr<IParser>;

View File

@ -33,7 +33,7 @@ namespace
return false;
ASTPtr new_settings_ast;
if (!ParserSettingsProfileElements{}.useIDMode(id_mode).parse(pos, new_settings_ast, expected))
if (!ParserSettingsProfileElements{}.useIDMode(id_mode).enableInheritKeyword(true).parse(pos, new_settings_ast, expected))
return false;
if (!settings)

View File

@ -7,11 +7,11 @@ namespace DB
{
/** Parses queries like
* CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]
*
* ALTER SETTINGS PROFILE [IF EXISTS] name
* [RENAME TO new_name]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]
*/
class ParserCreateSettingsProfileQuery : public IParserBase
{

View File

@ -108,7 +108,8 @@ bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected
Field max_value;
std::optional<bool> readonly;
if (ParserKeyword{"PROFILE"}.ignore(pos, expected))
if (ParserKeyword{"PROFILE"}.ignore(pos, expected) ||
(enable_inherit_keyword && ParserKeyword{"INHERIT"}.ignore(pos, expected)))
{
if (!parseProfileNameOrID(pos, expected, id_mode, parent_profile))
return false;
@ -120,9 +121,15 @@ bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected
return false;
name = getIdentifierName(name_ast);
bool has_value_or_constraint = false;
while (parseValue(pos, expected, value) || parseMinMaxValue(pos, expected, min_value, max_value)
|| parseReadonlyOrWritableKeyword(pos, expected, readonly))
;
{
has_value_or_constraint = true;
}
if (!has_value_or_constraint)
return false;
}
auto result = std::make_shared<ASTSettingsProfileElement>();
@ -133,6 +140,7 @@ bool ParserSettingsProfileElement::parseImpl(Pos & pos, ASTPtr & node, Expected
result->max_value = std::move(max_value);
result->readonly = readonly;
result->id_mode = id_mode;
result->use_inherit_keyword = enable_inherit_keyword;
node = result;
return true;
}
@ -142,12 +150,15 @@ bool ParserSettingsProfileElements::parseImpl(Pos & pos, ASTPtr & node, Expected
{
std::vector<std::shared_ptr<ASTSettingsProfileElement>> elements;
if (!ParserKeyword{"NONE"}.ignore(pos, expected))
if (ParserKeyword{"NONE"}.ignore(pos, expected))
{
}
else
{
do
{
ASTPtr ast;
if (!ParserSettingsProfileElement{}.useIDMode(id_mode).parse(pos, ast, expected))
if (!ParserSettingsProfileElement{}.useIDMode(id_mode).enableInheritKeyword(enable_inherit_keyword).parse(pos, ast, expected))
return false;
auto element = typeid_cast<std::shared_ptr<ASTSettingsProfileElement>>(ast);
elements.push_back(std::move(element));

View File

@ -12,6 +12,7 @@ class ParserSettingsProfileElement : public IParserBase
{
public:
ParserSettingsProfileElement & useIDMode(bool enable_) { id_mode = enable_; return *this; }
ParserSettingsProfileElement & enableInheritKeyword(bool enable_) { enable_inherit_keyword = enable_; return *this; }
protected:
const char * getName() const override { return "SettingsProfileElement"; }
@ -19,6 +20,7 @@ protected:
private:
bool id_mode = false;
bool enable_inherit_keyword = false;
};
@ -26,6 +28,7 @@ class ParserSettingsProfileElements : public IParserBase
{
public:
ParserSettingsProfileElements & useIDMode(bool enable_) { id_mode = enable_; return *this; }
ParserSettingsProfileElements & enableInheritKeyword(bool enable_) { enable_inherit_keyword = enable_; return *this; }
protected:
const char * getName() const override { return "SettingsProfileElements"; }
@ -33,4 +36,7 @@ protected:
private:
bool id_mode = false;
};}
bool enable_inherit_keyword = false;
};
}

View File

@ -47,7 +47,7 @@ def test_create():
assert instance.query("SHOW CREATE ROLE rx") == "CREATE ROLE rx SETTINGS PROFILE s1\n"
assert instance.query("SHOW GRANTS FOR rx") == ""
assert instance.query("SHOW CREATE SETTINGS PROFILE s1") == "CREATE SETTINGS PROFILE s1 SETTINGS max_memory_usage = 123456789 MIN 100000000 MAX 200000000\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE s2") == "CREATE SETTINGS PROFILE s2 SETTINGS PROFILE s1 TO u2\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE s2") == "CREATE SETTINGS PROFILE s2 SETTINGS INHERIT s1 TO u2\n"
check()
instance.restart_clickhouse() # Check persistency
@ -77,7 +77,7 @@ def test_alter():
assert instance.query("SHOW GRANTS FOR rx") == "GRANT SELECT ON mydb.* TO rx WITH GRANT OPTION\n"
assert instance.query("SHOW GRANTS FOR ry") == "GRANT rx TO ry WITH ADMIN OPTION\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE s1") == "CREATE SETTINGS PROFILE s1 SETTINGS max_memory_usage = 987654321 READONLY\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE s2") == "CREATE SETTINGS PROFILE s2 SETTINGS PROFILE s1 TO u2\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE s2") == "CREATE SETTINGS PROFILE s2 SETTINGS INHERIT s1 TO u2\n"
check()
instance.restart_clickhouse() # Check persistency

View File

@ -31,22 +31,26 @@ def reset_after_test():
def test_settings_profile():
# Set settings and constraints via CREATE SETTINGS PROFILE ... TO user
instance.query("CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "100000001\n"
assert "Setting max_memory_usage shouldn't be less than 90000000" in instance.query_and_get_error("SET max_memory_usage = 80000000", user="robin")
assert "Setting max_memory_usage shouldn't be greater than 110000000" in instance.query_and_get_error("SET max_memory_usage = 120000000", user="robin")
instance.query("ALTER SETTINGS PROFILE xyz TO NONE")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "10000000000\n"
instance.query("SET max_memory_usage = 80000000", user="robin")
instance.query("SET max_memory_usage = 120000000", user="robin")
# Set settings and constraints via CREATE USER ... SETTINGS PROFILE
instance.query("ALTER USER robin SETTINGS PROFILE xyz")
assert instance.query("SHOW CREATE USER robin") == "CREATE USER robin SETTINGS PROFILE xyz\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "100000001\n"
assert "Setting max_memory_usage shouldn't be less than 90000000" in instance.query_and_get_error("SET max_memory_usage = 80000000", user="robin")
assert "Setting max_memory_usage shouldn't be greater than 110000000" in instance.query_and_get_error("SET max_memory_usage = 120000000", user="robin")
instance.query("ALTER USER robin SETTINGS NONE")
assert instance.query("SHOW CREATE USER robin") == "CREATE USER robin\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "10000000000\n"
instance.query("SET max_memory_usage = 80000000", user="robin")
instance.query("SET max_memory_usage = 120000000", user="robin")
@ -57,6 +61,8 @@ def test_settings_profile_from_granted_role():
instance.query("CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000")
instance.query("CREATE ROLE worker SETTINGS PROFILE xyz")
instance.query("GRANT worker TO robin")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000\n"
assert instance.query("SHOW CREATE ROLE worker") == "CREATE ROLE worker SETTINGS PROFILE xyz\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "100000001\n"
assert "Setting max_memory_usage shouldn't be less than 90000000" in instance.query_and_get_error("SET max_memory_usage = 80000000", user="robin")
assert "Setting max_memory_usage shouldn't be greater than 110000000" in instance.query_and_get_error("SET max_memory_usage = 120000000", user="robin")
@ -68,17 +74,20 @@ def test_settings_profile_from_granted_role():
instance.query("ALTER ROLE worker SETTINGS NONE")
instance.query("GRANT worker TO robin")
assert instance.query("SHOW CREATE ROLE worker") == "CREATE ROLE worker\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "10000000000\n"
instance.query("SET max_memory_usage = 80000000", user="robin")
instance.query("SET max_memory_usage = 120000000", user="robin")
# Set settings and constraints via CREATE SETTINGS PROFILE ... TO granted role
instance.query("ALTER SETTINGS PROFILE xyz TO worker")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO worker\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "100000001\n"
assert "Setting max_memory_usage shouldn't be less than 90000000" in instance.query_and_get_error("SET max_memory_usage = 80000000", user="robin")
assert "Setting max_memory_usage shouldn't be greater than 110000000" in instance.query_and_get_error("SET max_memory_usage = 120000000", user="robin")
instance.query("ALTER SETTINGS PROFILE xyz TO NONE")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "10000000000\n"
instance.query("SET max_memory_usage = 80000000", user="robin")
instance.query("SET max_memory_usage = 120000000", user="robin")
@ -87,6 +96,8 @@ def test_settings_profile_from_granted_role():
def test_inheritance_of_settings_profile():
instance.query("CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000002 READONLY")
instance.query("CREATE SETTINGS PROFILE alpha SETTINGS PROFILE xyz TO robin")
assert instance.query("SHOW CREATE SETTINGS PROFILE xyz") == "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000002 READONLY\n"
assert instance.query("SHOW CREATE SETTINGS PROFILE alpha") == "CREATE SETTINGS PROFILE alpha SETTINGS INHERIT xyz TO robin\n"
assert instance.query("SELECT value FROM system.settings WHERE name = 'max_memory_usage'", user="robin") == "100000002\n"
assert "Setting max_memory_usage should not be changed" in instance.query_and_get_error("SET max_memory_usage = 80000000", user="robin")