Skip to content
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

sql/parser: Make ROLE a non-reserved keyword #24489

Closed
bdarnell opened this issue Apr 4, 2018 · 18 comments · Fixed by #24629
Closed

sql/parser: Make ROLE a non-reserved keyword #24489

bdarnell opened this issue Apr 4, 2018 · 18 comments · Fixed by #24629
Milestone

Comments

@bdarnell
Copy link
Contributor

bdarnell commented Apr 4, 2018

WORK became a reserved keyword in #20274, but it doesn't look like this is necessary. We should move it to the unreserved list to minimize disruption to applications that may have tables or columns with this name.

VIRTUAL and ROLE were also made reserved in 2.0, and we should see if we can move them too.

@jordanlewis
Copy link
Member

VIRTUAL and WORK are fixed now. ROLE is harder, because of the new SHOW GRANTS syntax that we added. I think we should consider removing or restricting some of that syntax, considering the pain it will inevitably cause (and has already started to cause - see cockroachdb/sqlalchemy-cockroachdb#50).

The problem is caused by the rules:

SHOW GRANTS ON ROLE opt_name_list for_grantee_clause

SHOW GRANTS on_privilege_target_clause for_grantee_clause

These are problematic rules because they're ambiguous. on_privilege_target_clause is either empty or ON targets. targets can be a list of table names. Table names could previously include the word role.

Therefore, it's impossible for the grammar to distinguish the syntax:

SHOW GRANTS ON ROLE

between parsing as the first rule and parsing as the second. That's why ROLE was added to the reserved keywords list - that resolves the problem, since the grammar now knows that ROLE can't be used as an unquoted table/target name.

This all being said, we need to figure out a way to move ROLE back to the unreserved keyword list. Unfortunately this is all but certain to require a backward-incompatible grammar change between 2.0 and the release we fix this in.

Some options are:

  • Change the syntax for SHOW GRANTS ON <table list> to be SHOW GRANTS FOR <table list>.
  • Force the table names in SHOW GRANTS ON <table list> to be quoted no matter what

@bdarnell
Copy link
Contributor Author

bdarnell commented Apr 6, 2018

Grammatically, I think I'd keep ON for SHOW GRANTS ON <tables> and use FOR for SHOW GRANTS FOR <role>. This also keeps the incompatible change to the new-in-2.0-enterprise syntax while preserving compatibility with the older SHOW GRANTS ON <tables>.

FWIW, we also reserve STORED, VIEW, LATERAL, NOTHING, and INDEX, while these are not reserved in postgres.

@jordanlewis
Copy link
Member

LATERAL and STORED are easily fixable; the others aren't. I'll send another PR for that.

@mberhault do you have any thoughts on this issue?

@knz
Copy link
Contributor

knz commented Apr 6, 2018

👍 on using FOR, for the same reasons as Ben's.

Regarding the other keywords, I'd propose trying to un-reserve them if possible. I recently came to the understanding that the move to reserve new keywords by default was cargo-culting previous grammar changes, not done principally, and I suspect several of the new keywords do not need to be reserved.

@knz
Copy link
Contributor

knz commented Apr 6, 2018

May I also suggest using this discussion as renewed motive to lock down grammar changes behind an additional level of scrutiny. Last time I suggested to do so, my proposal was shot down (for some good reasons, but one bad: I was also saying we'd run into this class of problems, and nobody believed me. Now there's proof) but I'd be willing to champion such an initiative again.

@mberhault
Copy link
Contributor

The problem with SHOW GRANTS is that in both cases (privileges and roles) the target (table or database or role) and user are both optional, so we need to way to distinguish between showing privileges and showing role memberships.

Now, we have a couple of options:

  • the postgres way: just don't have SHOW GRANTS. that kind of sucks, requiring special cli commands just to read this stuff is annoying.
  • the mysql way: SHOW GRANTS shows everything, with the FOR and ON clauses used to filter targets. Depending on how this is implemented, ROLE may or may not be used as a keyword.

In this specific case, ROLE wasn't moved to reserved willy-nilly, this was the only way to make this statement work. The fact that postgres does not do this is, in my opinion, a lack on their part.

@knz
Copy link
Contributor

knz commented Apr 6, 2018

In this specific case, ROLE wasn't moved to reserved willy-nilly, this was the only way to make this statement work.

Dissenting opinion: there was no good reason to use ON in ON ROLE.

@knz knz changed the title sql/parser: Make WORK a non-reserved keyword sql/parser: Make ROLE a non-reserved keyword Apr 6, 2018
@mberhault
Copy link
Contributor

Then the syntax is even weirder than usual SHOW GRANT ROLE <some role> FOR <some user>?

At some point, we either move the target logic into code (to determine if it's a db or table or role), we don't do role memberships, we keep role reserved, or we make show grants trivial (eg: no filtering of target, just the user. After checking the exact mysql grammar, turns out this is exactly what it does).

@bdarnell
Copy link
Contributor Author

bdarnell commented Apr 6, 2018

Or we could do something like SHOW ROLE GRANTS..., or use virtual tables instead of custom non-standard syntax. The grammar of SHOW statements should be kept simple and non-intrusive.

These contortions may be awkward, but they're worthwhile. Adding new reserved words breaks applications, so we should be very cautious about doing this. role is a fairly common name for columns, which is why this is coming up now while no one complained when we unnecessarily reserved STORED and LATERAL.

@knz
Copy link
Contributor

knz commented Apr 6, 2018

The real question IMHO is what sense does it make to call "show grants" the statement that tests "which user has which role" -- there's no idea of grant in there.

(Incidentally, I think it was a mistake to treat roles as permissions and "grant" them as permissions. They are really groups and we have role membership and group-level permissions. I'm not advocating changing the other statements accordingly, but it would be good to keep this reality in mind when evaluating syntax proposals.)

To me the following make sense:

  • SHOW USERS FROM <some role> (currently: SHOW GRANTS ON <some role>)
  • SHOW ROLES FOR <some user> (currently: SHOW GRANTS FOR <some user>)

@mberhault
Copy link
Contributor

The reason for this is that 1) roles are granted just like privileges (GRANT <role> TO <user>) and 2) mysql's introspection for role memberships is SHOW GRANTS. It was merely an attempt to limit surprises and to inject some semblance of logic in sql (ah!).

That said, SHOW ROLE MEMBERS (or similar) would work. I'm hesitant about SHOW USERES FROM <role>) as both roles and users are members of roles.

@knz
Copy link
Contributor

knz commented Apr 6, 2018

SHOW ROLE GRANTS and SHOW ROLE MEMBERS would work for me. I agree that SHOW USERS FROM is perhaps a bit too far-fetched.

@knz
Copy link
Contributor

knz commented Apr 6, 2018

FWIW @benesch just explained to me an alternate idea which would un-break the code for the 2.0 release without require a change in docs. I'll try to expand his idea.

craig bot added a commit that referenced this issue Apr 6, 2018
24561: sql: introduce the LATERAL keyword and mark it as unimplemented r=knz a=knz

CockroachDB aims to implement lateral joins. Until then, recognize
the syntax and link the error message to the appropriate support
issue.

This incidentally motivates keeping the keyword "reserved" in the
grammar.

Release note: None

Informs #24489.
Refers to #24560.
cc @petermattis
@knz
Copy link
Contributor

knz commented Apr 7, 2018

Folk the problem is really much worse than we thought: not only does this issue prevent new apps from working that want to use the reserved keywords as tables.

It also breaks existing databases -- any existing views that refer to tables named after new reserved keywords will now generate errors.

May I also suggest using this discussion as renewed motive to lock down grammar changes behind an additional level of scrutiny.

... including verification that the addition of any new reserved keyword is accompanied by a db migration that rewrites all views.

@petermattis
Copy link
Collaborator

@knz Is locking down the grammar necessary? From my reading of this discussion, it is the addition of new reserved keywords that is the problem.

PS Are you going to share the alternate idea that @benesch explained to you? I'm waiting eagerly to hear what it is.

@knz
Copy link
Contributor

knz commented Apr 7, 2018 via email

@petermattis
Copy link
Collaborator

I'm curious to see how that will work. SHOW GRANTS ON ROLE foo vs SHOW GRANTS ON role foo appear to be identical grammatically. I suppose you could make role special so that you can only do SHOW GRANTS ON "role". I wonder if you could achieve this is via something similar to the WITH_LA approach. That is, change the grammar to look for SHOW GRANTS ON_ROLE_LA where ON_ROLE_LA is a special token that looks for ON followed by an unquoted ROLE identifier.

petermattis added a commit to petermattis/cockroach that referenced this issue Apr 7, 2018
Use scanner lookahead to allow `SHOW GRANTS ON ROLE` despite `ROLE` not
being a reserved keyword. The user will have to type `SHOW GRANTS ON
"role"` in order to show the grants for a database named `role`.

TODO: `SHOW GRANTS ON "role"` does not round-trip properly and is output
as `SHOW GRANTS ON role`.

Fixes cockroachdb#24489

Release note (sql change): permit ROLE to be used as an unrestricted
name again.
petermattis added a commit to petermattis/cockroach that referenced this issue Apr 7, 2018
Use scanner lookahead to allow `SHOW GRANTS ON ROLE` despite `ROLE` not
being a reserved keyword. The user will have to type `SHOW GRANTS ON
"role"` in order to show the grants for a database named `role`.

Fixes cockroachdb#24489

Release note (sql change): permit ROLE to be used as an unrestricted
name again.
petermattis added a commit to petermattis/cockroach that referenced this issue Apr 10, 2018
Use scanner lookahead to allow `SHOW GRANTS ON ROLE` despite `ROLE` not
being a reserved keyword. The user will have to type `SHOW GRANTS ON
"role"` in order to show the grants for a database named `role`.

Fixes cockroachdb#24489

Release note (sql change): permit ROLE to be used as an unrestricted
name again.
@knz
Copy link
Contributor

knz commented Apr 10, 2018

Update: both Peter and I have a PR out to unreserve the keyword without changing the syntax (except for the very special case of SHOW GRANTS ON with a table named "role", where the table name now needs to be quoted).

We might pick one of these approaches to go to 2.0.1 (to unbreak apps immediately), but then I'd like to also immediately start the process to migrate/evolve the syntax to something different, for example using the FOR keyword instead, so as to remove the code and complexity that either of our PRs is adding and reduce tech debt.

craig bot pushed a commit that referenced this issue Apr 11, 2018
24629: sql: make ROLE a non-reserved keyword r=knz a=knz

Fixes #24489.
Alternative to #24581.

When support for role-based access control was added, the ROLE
identifier became a reserved keyword. This breaks existing apps and
databases which use the word "role" to name databases, tables or
columns, which as experience shows seems to be a pretty common occurence.

This change un-breaks the existing apps and databases by making the
keyword non-reserved again. This change avoids redefinition of the
syntax of the SHOW GRANTS ON ROLE statement, at the cost of a
non-trivial, poorly maintainable and gross hack to the SQL grammar.

Release note (sql change, bug fix): the word "ROLE" is not a reserved
keyword any more, which (re-)enables database and apps using that name
for databases, tables and columns.

Co-authored-by: Raphael 'kena' Poss <knz@cockroachlabs.com>
@craig craig bot closed this as completed in #24629 Apr 11, 2018
@knz knz added docs-todo and removed docs-todo labels May 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants