-
Notifications
You must be signed in to change notification settings - Fork 7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CHECK GRANT query #68885
Add CHECK GRANT query #68885
Conversation
This is an automated comment for commit 1f7be09 with description of existing statuses. It's updated for the latest CI running ✅ Click here to open a full report in a separate page Successful checks
|
Please check the pr. The stateless test failure seems to be not related to my codes. @vitlibar @alexey-milovidov |
title: "CHECK GRANT Statement" | ||
--- | ||
|
||
The `CHECK GRANT` query is used to check whether the current user/role has been granted a specific privilege, and whether the corresponding table/column exists in the memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Unalian Why do you think CHECK GRANT
should check that the corresponding table/column exists in the memory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on the describe of the issue.@Unalian Why do you think
CHECK GRANT
should check that the corresponding table/column exists in the memory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, if a table doesn't exist then
DROP TABLE IF EXISTS db.mytable
still works, and that requires privilege GRANT DROP TABLE ON db.mytable
.
But what is the point of checking the table's existence in CHECK GRANTS
in this case?
CHECK GRANT DROP TABLE ON db.mytable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we need either a setting to enable/disable checking existence in CHECK GRANT
or just separate commands to check grants only or to check existence only. We already have the EXISTS TABLE
command, so I think we can have EXISTS COLUMNS
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, if a table doesn't exist then
DROP TABLE IF EXISTS db.mytable
still works, and that requires privilege
GRANT DROP TABLE ON db.mytable
.But what is the point of checking
CHECK GRANT DROP TABLE ON db.mytable
in this case?
CHECK GRANT DROP TABLE ON db.mytable
will return if the user has privilege to DROP TABLE ON db.mytable
and the db.mytable
exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHECK GRANT DROP TABLE ON db.mytable
will return if the user has privilege to DROP TABLE ON db.mytable and the db.mytable exists
Yes, but this is not what some users might expect from command CHECK GRANT DROP TABLE ON db.mytable
in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we need either a setting to enable/disable checking existence in
CHECK GRANT
or separate commands to check grants only or to check existence only. We already have theEXISTS TABLE
command, so I think we can haveEXISTS COLUMNS
as well.
I got your point. Separating the commands to check grants only or to check existence only may be better. Actually, that is what I am thinking about during coding(#67772 (comment)). I will change the logic here (remove the existence check in check grant). Then, maybe add EXISTS COLUMNS
just like EXISTS TABLE
as well.
if (!founded) | ||
{ | ||
/// Column not found. | ||
return executeQuery("SELECT 0 AS CHECK_GRANT", getContext(), QueryFlags{.internal = true}).second; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling executeQuery
is a quite heavy way to just return 0
as a result.
It's much better to just build the result block here from scratch - in the same way how it's built in InterpreterExistsQuery
:
return QueryPipeline(std::make_shared<SourceFromSingleChunk>(Block{{
ColumnUInt8::create(1, result),
std::make_shared<DataTypeUInt8>(),
"result" }}));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
executeQuery
is a quite heavy way to just return0
as a result.It's much better to just build the result block here from scratch - in the same way how it's built in
InterpreterExistsQuery
:return QueryPipeline(std::make_shared<SourceFromSingleChunk>(Block{{ ColumnUInt8::create(1, result), std::make_shared<DataTypeUInt8>(), "result" }}));
Got it.
…certain access rights elements && the elements exist).
…nt; Update the way to return result.
} | ||
BlockIO res; | ||
res.pipeline = QueryPipeline( | ||
std::make_shared<SourceFromSingleChunk>(Block{{ColumnUInt8::create(1, 1), std::make_shared<DataTypeUInt8>(), "result"}})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use user_is_granted
right in the arguments of ColumnUInt8::create()
, there is no need to repeat the same code again:
BlockIO res;
res.pipeline = QueryPipeline(
std::make_shared<SourceFromSingleChunk>(Block{{ColumnUInt8::create(1, user_is_granted), std::make_shared<DataTypeUInt8>(), "result"}}));
AccessRightsElements elements_to_check_grant; | ||
collectAccessRightsElementsToGrantOrRevoke(query, elements_to_check_grant); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two lines can be replaced with just one:
AccessRightsElements elements_to_check_grant; | |
collectAccessRightsElementsToGrantOrRevoke(query, elements_to_check_grant); | |
const AccessRightsElements & elements_to_check_grant = query.access_rights_elements; |
and function collectAccessRightsElementsToGrantOrRevoke
is not needed in this file.
…ateless-test case about check grant wildcard
|
||
settings.ostr << " "; | ||
|
||
formatElementsWithoutOptions(access_rights_elements, settings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't you use
settings.ostr << access_rights_element.toString();
here instead of calling this function formatElementsWithoutOptions()
which looks like a lot of copy-paste?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't you use
settings.ostr << access_rights_element.toString();
here instead of calling this function
formatElementsWithoutOptions()
which looks like a lot of copy-paste?
The function does some format works in formatFunction(). Suppose I use settings.ostr << access_rights_element.toString();
here, such query's format will be like (which is created by Parser):
:) check grant select(col,col2) on tb, alter on tb2
CHECK GRANT SELECT(col, col2) ON tb, GRANT ALTER TABLE, ALTER VIEW ON tb2
Query id: 5f3927b0-8d99-4db2-a702-67e53955476c
┌─result─┐
1. │ 1 │
└────────┘
1 row in set. Elapsed: 0.001 sec.
However, the correct response should be just like GRANT
keyword:
:) check grant select(col,col2) on tb, alter on tb2
CHECK GRANT SELECT(col, col2) ON tb, ALTER TABLE, ALTER VIEW ON tb2
Query id: b48aabc2-2b6e-45ed-a36a-7802a00e3852
┌─result─┐
1. │ 1 │
└────────┘
1 row in set. Elapsed: 0.001 sec.
I will pollish the formatFunction here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main problem with your functions is that they look like a lot of copy-pasted code which isn't good. Perhaps you could get rid of at least formatColumnNames
& formatONClause
?
} | ||
|
||
bool parseAccessFlagsWithColumns(IParser::Pos & pos, Expected & expected, | ||
std::vector<std::pair<AccessFlags, Strings>> & access_and_columns) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move common functions such as parseAccessFlags
, parseColumnNames
, parseAccessFlagsWithColumns
, parseElements
to some separate source file (src/Parser/Access/parseAccessRightsElements.h/cpp
), where both ParserCheckGrantQuery.cpp
and ParserGrantQuery.cpp
could use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move common functions such as
parseAccessFlags
,parseColumnNames
,parseAccessFlagsWithColumns
,parseElements
to some separate source file (src/Parser/Access/parseAccessRightsElements.h/cpp
), where bothParserCheckGrantQuery.cpp
andParserGrantQuery.cpp
could use it.
Got it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to that by myself
#72103
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
353ff95
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Add
CHECK GRANT
query to check whether the current user/role has been granted the specific privilege and whether the corresponding table/column exists in the memory.Documentation entry for user-facing changes
CI Settings (Only check the boxes if you know what you are doing):