mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
Simplify DCL for creating quotas.
This commit is contained in:
parent
23ac1ee87c
commit
d548c7e381
@ -34,7 +34,7 @@ void updateQuotaFromQueryImpl(Quota & quota, const ASTCreateQuotaQuery & query,
|
|||||||
auto duration = query_limits.duration;
|
auto duration = query_limits.duration;
|
||||||
|
|
||||||
auto it = boost::range::find_if(quota_all_limits, [&](const Quota::Limits & x) { return x.duration == duration; });
|
auto it = boost::range::find_if(quota_all_limits, [&](const Quota::Limits & x) { return x.duration == duration; });
|
||||||
if (query_limits.unset_tracking)
|
if (query_limits.drop)
|
||||||
{
|
{
|
||||||
if (it != quota_all_limits.end())
|
if (it != quota_all_limits.end())
|
||||||
quota_all_limits.erase(it);
|
quota_all_limits.erase(it);
|
||||||
@ -59,6 +59,8 @@ void updateQuotaFromQueryImpl(Quota & quota, const ASTCreateQuotaQuery & query,
|
|||||||
{
|
{
|
||||||
if (query_limits.max[resource_type])
|
if (query_limits.max[resource_type])
|
||||||
quota_limits.max[resource_type] = *query_limits.max[resource_type];
|
quota_limits.max[resource_type] = *query_limits.max[resource_type];
|
||||||
|
else
|
||||||
|
quota_limits.max[resource_type] = Quota::UNLIMITED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ namespace
|
|||||||
create_query_limits.duration = limits.duration;
|
create_query_limits.duration = limits.duration;
|
||||||
create_query_limits.randomize_interval = limits.randomize_interval;
|
create_query_limits.randomize_interval = limits.randomize_interval;
|
||||||
for (auto resource_type : ext::range(Quota::MAX_RESOURCE_TYPE))
|
for (auto resource_type : ext::range(Quota::MAX_RESOURCE_TYPE))
|
||||||
if (limits.max[resource_type])
|
if (limits.max[resource_type] != Quota::UNLIMITED)
|
||||||
create_query_limits.max[resource_type] = limits.max[resource_type];
|
create_query_limits.max[resource_type] = limits.max[resource_type];
|
||||||
query->all_limits.push_back(create_query_limits);
|
query->all_limits.push_back(create_query_limits);
|
||||||
}
|
}
|
||||||
|
@ -28,16 +28,17 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void formatLimit(ResourceType resource_type, ResourceAmount max, const IAST::FormatSettings & settings)
|
void formatLimit(ResourceType resource_type, ResourceAmount max, bool first, const IAST::FormatSettings & settings)
|
||||||
{
|
{
|
||||||
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " MAX " << Quota::resourceTypeToKeyword(resource_type)
|
if (first)
|
||||||
<< (settings.hilite ? IAST::hilite_none : "");
|
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " MAX" << (settings.hilite ? IAST::hilite_none : "");
|
||||||
|
else
|
||||||
|
settings.ostr << ",";
|
||||||
|
|
||||||
settings.ostr << (settings.hilite ? IAST::hilite_operator : "") << " = " << (settings.hilite ? IAST::hilite_none : "");
|
settings.ostr << " " << (settings.hilite ? IAST::hilite_keyword : "") << Quota::resourceTypeToKeyword(resource_type)
|
||||||
|
<< (settings.hilite ? IAST::hilite_none : "") << " ";
|
||||||
|
|
||||||
if (max == Quota::UNLIMITED)
|
if (resource_type == Quota::EXECUTION_TIME)
|
||||||
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << "ANY" << (settings.hilite ? IAST::hilite_none : "");
|
|
||||||
else if (resource_type == Quota::EXECUTION_TIME)
|
|
||||||
settings.ostr << Quota::executionTimeToSeconds(max);
|
settings.ostr << Quota::executionTimeToSeconds(max);
|
||||||
else
|
else
|
||||||
settings.ostr << max;
|
settings.ostr << max;
|
||||||
@ -59,9 +60,9 @@ namespace
|
|||||||
<< interval_kind.toKeyword()
|
<< interval_kind.toKeyword()
|
||||||
<< (settings.hilite ? IAST::hilite_none : "");
|
<< (settings.hilite ? IAST::hilite_none : "");
|
||||||
|
|
||||||
if (limits.unset_tracking)
|
if (limits.drop)
|
||||||
{
|
{
|
||||||
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " UNSET TRACKING" << (settings.hilite ? IAST::hilite_none : "");
|
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " NO LIMITS" << (settings.hilite ? IAST::hilite_none : "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -70,14 +71,12 @@ namespace
|
|||||||
{
|
{
|
||||||
if (limits.max[resource_type])
|
if (limits.max[resource_type])
|
||||||
{
|
{
|
||||||
if (limit_found)
|
formatLimit(resource_type, *limits.max[resource_type], !limit_found, settings);
|
||||||
settings.ostr << ",";
|
|
||||||
limit_found = true;
|
limit_found = true;
|
||||||
formatLimit(resource_type, *limits.max[resource_type], settings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!limit_found)
|
if (!limit_found)
|
||||||
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " TRACKING" << (settings.hilite ? IAST::hilite_none : "");
|
settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " TRACKING ONLY" << (settings.hilite ? IAST::hilite_none : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,17 +13,16 @@ class ASTExtendedRoleSet;
|
|||||||
/** CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name
|
/** CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name
|
||||||
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||||
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
||||||
* {[SET] MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = {number | ANY} } [,...] |
|
* {MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number} [,...] |
|
||||||
* [SET] TRACKING} [,...]]
|
* NO LIMITS | TRACKING ONLY} [,...]]
|
||||||
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||||
*
|
*
|
||||||
* ALTER QUOTA [IF EXISTS] name
|
* ALTER QUOTA [IF EXISTS] name
|
||||||
* [RENAME TO new_name]
|
* [RENAME TO new_name]
|
||||||
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||||
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
||||||
* {[SET] MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = {number | ANY} } [,...] |
|
* {MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number} [,...] |
|
||||||
* [SET] TRACKING |
|
* NO LIMITS | TRACKING ONLY} [,...]]
|
||||||
* UNSET TRACKING} [,...]]
|
|
||||||
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||||
*/
|
*/
|
||||||
class ASTCreateQuotaQuery : public IAST, public ASTQueryWithOnCluster
|
class ASTCreateQuotaQuery : public IAST, public ASTQueryWithOnCluster
|
||||||
@ -48,7 +47,7 @@ public:
|
|||||||
struct Limits
|
struct Limits
|
||||||
{
|
{
|
||||||
std::optional<ResourceAmount> max[MAX_RESOURCE_TYPE];
|
std::optional<ResourceAmount> max[MAX_RESOURCE_TYPE];
|
||||||
bool unset_tracking = false;
|
bool drop = false;
|
||||||
std::chrono::seconds duration = std::chrono::seconds::zero();
|
std::chrono::seconds duration = std::chrono::seconds::zero();
|
||||||
bool randomize_interval = false;
|
bool randomize_interval = false;
|
||||||
};
|
};
|
||||||
|
@ -63,12 +63,22 @@ namespace
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseLimit(IParserBase::Pos & pos, Expected & expected, ResourceType & resource_type, ResourceAmount & max)
|
bool parseLimit(IParserBase::Pos & pos, Expected & expected, bool first, ResourceType & resource_type, ResourceAmount & max)
|
||||||
{
|
{
|
||||||
return IParserBase::wrapParseImpl(pos, [&]
|
return IParserBase::wrapParseImpl(pos, [&]
|
||||||
{
|
{
|
||||||
if (!ParserKeyword{"MAX"}.ignore(pos, expected))
|
if (first)
|
||||||
return false;
|
{
|
||||||
|
if (!ParserKeyword{"MAX"}.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ParserToken{TokenType::Comma}.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParserKeyword{"MAX"}.ignore(pos, expected);
|
||||||
|
}
|
||||||
|
|
||||||
bool resource_type_set = false;
|
bool resource_type_set = false;
|
||||||
for (auto rt : ext::range_with_static_cast<Quota::ResourceType>(Quota::MAX_RESOURCE_TYPE))
|
for (auto rt : ext::range_with_static_cast<Quota::ResourceType>(Quota::MAX_RESOURCE_TYPE))
|
||||||
@ -83,9 +93,6 @@ namespace
|
|||||||
if (!resource_type_set)
|
if (!resource_type_set)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ParserToken{TokenType::Equals}.ignore(pos, expected))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ASTPtr max_ast;
|
ASTPtr max_ast;
|
||||||
if (ParserNumber{}.parse(pos, max_ast, expected))
|
if (ParserNumber{}.parse(pos, max_ast, expected))
|
||||||
{
|
{
|
||||||
@ -95,10 +102,6 @@ namespace
|
|||||||
else
|
else
|
||||||
max = applyVisitor(FieldVisitorConvertToNumber<ResourceAmount>(), max_field);
|
max = applyVisitor(FieldVisitorConvertToNumber<ResourceAmount>(), max_field);
|
||||||
}
|
}
|
||||||
else if (ParserKeyword{"ANY"}.ignore(pos, expected))
|
|
||||||
{
|
|
||||||
max = Quota::UNLIMITED;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -106,18 +109,7 @@ namespace
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseCommaAndLimit(IParserBase::Pos & pos, Expected & expected, ResourceType & resource_type, ResourceAmount & max)
|
bool parseLimits(IParserBase::Pos & pos, Expected & expected, ASTCreateQuotaQuery::Limits & limits)
|
||||||
{
|
|
||||||
return IParserBase::wrapParseImpl(pos, [&]
|
|
||||||
{
|
|
||||||
if (!ParserToken{TokenType::Comma}.ignore(pos, expected))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return parseLimit(pos, expected, resource_type, max);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parseLimits(IParserBase::Pos & pos, Expected & expected, bool alter, ASTCreateQuotaQuery::Limits & limits)
|
|
||||||
{
|
{
|
||||||
return IParserBase::wrapParseImpl(pos, [&]
|
return IParserBase::wrapParseImpl(pos, [&]
|
||||||
{
|
{
|
||||||
@ -142,23 +134,22 @@ namespace
|
|||||||
|
|
||||||
new_limits.duration = std::chrono::seconds(static_cast<UInt64>(num_intervals * interval_kind.toAvgSeconds()));
|
new_limits.duration = std::chrono::seconds(static_cast<UInt64>(num_intervals * interval_kind.toAvgSeconds()));
|
||||||
|
|
||||||
if (alter && ParserKeyword{"UNSET TRACKING"}.ignore(pos, expected))
|
if (ParserKeyword{"NO LIMITS"}.ignore(pos, expected))
|
||||||
{
|
{
|
||||||
new_limits.unset_tracking = true;
|
new_limits.drop = true;
|
||||||
}
|
}
|
||||||
else if (ParserKeyword{"SET TRACKING"}.ignore(pos, expected) || ParserKeyword{"TRACKING"}.ignore(pos, expected))
|
else if (ParserKeyword{"TRACKING ONLY"}.ignore(pos, expected))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParserKeyword{"SET"}.ignore(pos, expected);
|
|
||||||
ResourceType resource_type;
|
ResourceType resource_type;
|
||||||
ResourceAmount max;
|
ResourceAmount max;
|
||||||
if (!parseLimit(pos, expected, resource_type, max))
|
if (!parseLimit(pos, expected, true, resource_type, max))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
new_limits.max[resource_type] = max;
|
new_limits.max[resource_type] = max;
|
||||||
while (parseCommaAndLimit(pos, expected, resource_type, max))
|
while (parseLimit(pos, expected, false, resource_type, max))
|
||||||
new_limits.max[resource_type] = max;
|
new_limits.max[resource_type] = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +158,7 @@ namespace
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseAllLimits(IParserBase::Pos & pos, Expected & expected, bool alter, std::vector<ASTCreateQuotaQuery::Limits> & all_limits)
|
bool parseAllLimits(IParserBase::Pos & pos, Expected & expected, std::vector<ASTCreateQuotaQuery::Limits> & all_limits)
|
||||||
{
|
{
|
||||||
return IParserBase::wrapParseImpl(pos, [&]
|
return IParserBase::wrapParseImpl(pos, [&]
|
||||||
{
|
{
|
||||||
@ -175,7 +166,7 @@ namespace
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
ASTCreateQuotaQuery::Limits limits;
|
ASTCreateQuotaQuery::Limits limits;
|
||||||
if (!parseLimits(pos, expected, alter, limits))
|
if (!parseLimits(pos, expected, limits))
|
||||||
{
|
{
|
||||||
all_limits.resize(old_size);
|
all_limits.resize(old_size);
|
||||||
return false;
|
return false;
|
||||||
@ -257,7 +248,7 @@ bool ParserCreateQuotaQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expe
|
|||||||
if (!key_type && parseKeyType(pos, expected, key_type))
|
if (!key_type && parseKeyType(pos, expected, key_type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (parseAllLimits(pos, expected, alter, all_limits))
|
if (parseAllLimits(pos, expected, all_limits))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -9,17 +9,16 @@ namespace DB
|
|||||||
* CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name
|
* CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name
|
||||||
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||||
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
||||||
* {[SET] MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = {number | ANY} } [,...] |
|
* {MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number} [,...] |
|
||||||
* [SET] TRACKING} [,...]]
|
* NO LIMITS | TRACKING ONLY} [,...]]
|
||||||
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||||
*
|
*
|
||||||
* ALTER QUOTA [IF EXISTS] name
|
* ALTER QUOTA [IF EXISTS] name
|
||||||
* [RENAME TO new_name]
|
* [RENAME TO new_name]
|
||||||
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
* [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||||
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
* [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
||||||
* {[SET] MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = {number | ANY} } [,...] |
|
* {MAX {{QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number} } [,...] |
|
||||||
* [SET] TRACKING |
|
* NO LIMITS | TRACKING ONLY} [,...]]
|
||||||
* UNSET TRACKING} [,...]]
|
|
||||||
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
* [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||||
*/
|
*/
|
||||||
class ParserCreateQuotaQuery : public IParserBase
|
class ParserCreateQuotaQuery : public IParserBase
|
||||||
|
@ -22,7 +22,7 @@ def create_entities():
|
|||||||
instance.query("CREATE USER u2 IDENTIFIED BY 'qwerty' HOST LOCAL DEFAULT ROLE rx")
|
instance.query("CREATE USER u2 IDENTIFIED BY 'qwerty' HOST LOCAL DEFAULT ROLE rx")
|
||||||
instance.query("CREATE SETTINGS PROFILE s2 SETTINGS PROFILE s1 TO u2")
|
instance.query("CREATE SETTINGS PROFILE s2 SETTINGS PROFILE s1 TO u2")
|
||||||
instance.query("CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a<1000 TO u1, u2")
|
instance.query("CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a<1000 TO u1, u2")
|
||||||
instance.query("CREATE QUOTA q FOR INTERVAL 1 HOUR SET MAX QUERIES = 100 TO ALL EXCEPT rx")
|
instance.query("CREATE QUOTA q FOR INTERVAL 1 HOUR MAX QUERIES 100 TO ALL EXCEPT rx")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -41,7 +41,7 @@ def test_create():
|
|||||||
assert instance.query("SHOW CREATE USER u1") == "CREATE USER u1 SETTINGS PROFILE s1\n"
|
assert instance.query("SHOW CREATE USER u1") == "CREATE USER u1 SETTINGS PROFILE s1\n"
|
||||||
assert instance.query("SHOW CREATE USER u2") == "CREATE USER u2 HOST LOCAL DEFAULT ROLE rx\n"
|
assert instance.query("SHOW CREATE USER u2") == "CREATE USER u2 HOST LOCAL DEFAULT ROLE rx\n"
|
||||||
assert instance.query("SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 TO u1, u2\n"
|
assert instance.query("SHOW CREATE ROW POLICY p ON mydb.mytable") == "CREATE ROW POLICY p ON mydb.mytable FOR SELECT USING a < 1000 TO u1, u2\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA q") == "CREATE QUOTA q KEYED BY \\'none\\' FOR INTERVAL 1 HOUR MAX QUERIES = 100 TO ALL EXCEPT rx\n"
|
assert instance.query("SHOW CREATE QUOTA q") == "CREATE QUOTA q KEYED BY \\'none\\' FOR INTERVAL 1 HOUR MAX QUERIES 100 TO ALL EXCEPT rx\n"
|
||||||
assert instance.query("SHOW GRANTS FOR u1") == ""
|
assert instance.query("SHOW GRANTS FOR u1") == ""
|
||||||
assert instance.query("SHOW GRANTS FOR u2") == "GRANT rx TO u2\n"
|
assert instance.query("SHOW GRANTS FOR u2") == "GRANT rx TO u2\n"
|
||||||
assert instance.query("SHOW CREATE ROLE rx") == "CREATE ROLE rx SETTINGS PROFILE s1\n"
|
assert instance.query("SHOW CREATE ROLE rx") == "CREATE ROLE rx SETTINGS PROFILE s1\n"
|
||||||
|
@ -180,7 +180,7 @@ def test_reload_users_xml_by_timer():
|
|||||||
|
|
||||||
def test_dcl_introspection():
|
def test_dcl_introspection():
|
||||||
assert instance.query("SHOW QUOTAS") == "myQuota\n"
|
assert instance.query("SHOW QUOTAS") == "myQuota\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES = 1000, MAX READ ROWS = 1000 TO default\n"
|
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES 1000, READ ROWS 1000 TO default\n"
|
||||||
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=0/1000 errors=0 result_rows=0 result_bytes=0 read_rows=0/1000 read_bytes=0 execution_time=0"
|
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=0/1000 errors=0 result_rows=0 result_bytes=0 read_rows=0/1000 read_bytes=0 execution_time=0"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE CURRENT"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE CURRENT"))
|
||||||
@ -193,7 +193,7 @@ def test_dcl_introspection():
|
|||||||
# Add interval.
|
# Add interval.
|
||||||
copy_quota_xml('two_intervals.xml')
|
copy_quota_xml('two_intervals.xml')
|
||||||
assert instance.query("SHOW QUOTAS") == "myQuota\n"
|
assert instance.query("SHOW QUOTAS") == "myQuota\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES = 1000, MAX READ ROWS = 1000, FOR RANDOMIZED INTERVAL 2 YEAR MAX RESULT BYTES = 30000, MAX READ BYTES = 20000, MAX EXECUTION TIME = 120 TO default\n"
|
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES 1000, READ ROWS 1000, FOR RANDOMIZED INTERVAL 2 YEAR MAX RESULT BYTES 30000, READ BYTES 20000, EXECUTION TIME 120 TO default\n"
|
||||||
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=1/1000 errors=0 result_rows=50 result_bytes=200 read_rows=50/1000 read_bytes=200 execution_time=.*\n"\
|
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=1/1000 errors=0 result_rows=50 result_bytes=200 read_rows=50/1000 read_bytes=200 execution_time=.*\n"\
|
||||||
"myQuota key=\\\\'default\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0/30000 read_rows=0 read_bytes=0/20000 execution_time=0/120"
|
"myQuota key=\\\\'default\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0/30000 read_rows=0 read_bytes=0/20000 execution_time=0/120"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
@ -201,8 +201,8 @@ def test_dcl_introspection():
|
|||||||
# Drop interval, add quota.
|
# Drop interval, add quota.
|
||||||
copy_quota_xml('two_quotas.xml')
|
copy_quota_xml('two_quotas.xml')
|
||||||
assert instance.query("SHOW QUOTAS") == "myQuota\nmyQuota2\n"
|
assert instance.query("SHOW QUOTAS") == "myQuota\nmyQuota2\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES = 1000, MAX READ ROWS = 1000 TO default\n"
|
assert instance.query("SHOW CREATE QUOTA myQuota") == "CREATE QUOTA myQuota KEYED BY \\'user name\\' FOR INTERVAL 1 YEAR MAX QUERIES 1000, READ ROWS 1000 TO default\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA myQuota2") == "CREATE QUOTA myQuota2 KEYED BY \\'client key or user name\\' FOR RANDOMIZED INTERVAL 1 HOUR MAX RESULT ROWS = 4000, MAX RESULT BYTES = 400000, MAX READ ROWS = 4000, MAX READ BYTES = 400000, MAX EXECUTION TIME = 60, FOR INTERVAL 1 MONTH MAX EXECUTION TIME = 1800\n"
|
assert instance.query("SHOW CREATE QUOTA myQuota2") == "CREATE QUOTA myQuota2 KEYED BY \\'client key or user name\\' FOR RANDOMIZED INTERVAL 1 HOUR MAX RESULT ROWS 4000, RESULT BYTES 400000, READ ROWS 4000, READ BYTES 400000, EXECUTION TIME 60, FOR INTERVAL 1 MONTH MAX EXECUTION TIME 1800\n"
|
||||||
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=1/1000 errors=0 result_rows=50 result_bytes=200 read_rows=50/1000 read_bytes=200 execution_time=.*"
|
expected_usage = "myQuota key=\\\\'default\\\\' interval=\[.*\] queries=1/1000 errors=0 result_rows=50 result_bytes=200 read_rows=50/1000 read_bytes=200 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
@ -212,9 +212,9 @@ def test_dcl_management():
|
|||||||
assert instance.query("SHOW QUOTAS") == ""
|
assert instance.query("SHOW QUOTAS") == ""
|
||||||
assert instance.query("SHOW QUOTA USAGE") == ""
|
assert instance.query("SHOW QUOTA USAGE") == ""
|
||||||
|
|
||||||
instance.query("CREATE QUOTA qA FOR INTERVAL 15 MONTH SET MAX QUERIES = 123 TO CURRENT_USER")
|
instance.query("CREATE QUOTA qA FOR INTERVAL 15 MONTH MAX QUERIES 123 TO CURRENT_USER")
|
||||||
assert instance.query("SHOW QUOTAS") == "qA\n"
|
assert instance.query("SHOW QUOTAS") == "qA\n"
|
||||||
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR INTERVAL 5 QUARTER MAX QUERIES = 123 TO default\n"
|
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR INTERVAL 5 QUARTER MAX QUERIES 123 TO default\n"
|
||||||
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0/123 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*"
|
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0/123 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
@ -222,14 +222,14 @@ def test_dcl_management():
|
|||||||
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=1/123 errors=0 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=1/123 errors=0 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
instance.query("ALTER QUOTA qA FOR INTERVAL 15 MONTH MAX QUERIES = 321, MAX ERRORS = 10, FOR INTERVAL 0.5 HOUR MAX EXECUTION TIME = 0.5")
|
instance.query("ALTER QUOTA qA FOR INTERVAL 15 MONTH MAX QUERIES 321, MAX ERRORS 10, FOR INTERVAL 0.5 HOUR MAX EXECUTION TIME 0.5")
|
||||||
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR INTERVAL 30 MINUTE MAX EXECUTION TIME = 0.5, FOR INTERVAL 5 QUARTER MAX QUERIES = 321, MAX ERRORS = 10 TO default\n"
|
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR INTERVAL 30 MINUTE MAX EXECUTION TIME 0.5, FOR INTERVAL 5 QUARTER MAX QUERIES 321, ERRORS 10 TO default\n"
|
||||||
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*/0.5\n"\
|
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*/0.5\n"\
|
||||||
"qA key=\\\\'\\\\' interval=\[.*\] queries=1/321 errors=0/10 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
"qA key=\\\\'\\\\' interval=\[.*\] queries=1/321 errors=0/10 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
instance.query("ALTER QUOTA qA FOR INTERVAL 15 MONTH UNSET TRACKING, FOR RANDOMIZED INTERVAL 16 MONTH SET TRACKING, FOR INTERVAL 1800 SECOND UNSET TRACKING")
|
instance.query("ALTER QUOTA qA FOR INTERVAL 15 MONTH NO LIMITS, FOR RANDOMIZED INTERVAL 16 MONTH TRACKING ONLY, FOR INTERVAL 1800 SECOND NO LIMITS")
|
||||||
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR RANDOMIZED INTERVAL 16 MONTH TRACKING TO default\n"
|
assert instance.query("SHOW CREATE QUOTA qA") == "CREATE QUOTA qA KEYED BY \\'none\\' FOR RANDOMIZED INTERVAL 16 MONTH TRACKING ONLY TO default\n"
|
||||||
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*"
|
expected_usage = "qA key=\\\\'\\\\' interval=\[.*\] queries=0 errors=0 result_rows=0 result_bytes=0 read_rows=0 read_bytes=0 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ def test_dcl_management():
|
|||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
instance.query("ALTER QUOTA qA RENAME TO qB")
|
instance.query("ALTER QUOTA qA RENAME TO qB")
|
||||||
assert instance.query("SHOW CREATE QUOTA qB") == "CREATE QUOTA qB KEYED BY \\'none\\' FOR RANDOMIZED INTERVAL 16 MONTH TRACKING TO default\n"
|
assert instance.query("SHOW CREATE QUOTA qB") == "CREATE QUOTA qB KEYED BY \\'none\\' FOR RANDOMIZED INTERVAL 16 MONTH TRACKING ONLY TO default\n"
|
||||||
expected_usage = "qB key=\\\\'\\\\' interval=\[.*\] queries=1 errors=0 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
expected_usage = "qB key=\\\\'\\\\' interval=\[.*\] queries=1 errors=0 result_rows=50 result_bytes=200 read_rows=50 read_bytes=200 execution_time=.*"
|
||||||
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
assert re.match(expected_usage, instance.query("SHOW QUOTA USAGE"))
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
default
|
default
|
||||||
CREATE QUOTA default KEYED BY \'user name\' FOR INTERVAL 1 HOUR TRACKING TO default, readonly
|
CREATE QUOTA default KEYED BY \'user name\' FOR INTERVAL 1 HOUR TRACKING ONLY TO default, readonly
|
||||||
|
Loading…
Reference in New Issue
Block a user