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

planner/core: fix privilege check for update #10281

Merged
merged 5 commits into from
Apr 30, 2019

Conversation

tiancaiamao
Copy link
Contributor

@tiancaiamao tiancaiamao commented Apr 26, 2019

What problem does this PR solve?

create database service;
create database report;
CREATE TABLE service.t1 (
  id int(11) DEFAULT NULL,
  a bigint(20) NOT NULL,
  b text DEFAULT NULL,
  PRIMARY KEY (a)
);
CREATE TABLE report.t2 (
  a bigint(20) DEFAULT NULL,
  c bigint(20) NOT NULL
);
create user 'test'@'%';
grant all privileges on service.* to test;
grant all privileges on report.* to test;

Login as test, run this update statement:

mysql> update service.t1 s,
    -> report.t2 t
    -> set s.a = t.a
    -> WHERE
    -> s.a = t.a
    -> and t.c >=  1 and t.c <= 10000
    -> and s.b !='xx';
ERROR 1105 (HY000): privilege check fail

What is changed and how it works?

One of the visitInfo record is

db=""
table="t1"
user="test"

It doesn't match any privilege record in the cache, so privilege check fail.

The bug is, db should not be "" here.

Check List

Tests

  • Unit test
  • Manual test (add detailed scripts or steps below)

Related change

  • Need to cherry-pick to the release branch

@tiancaiamao
Copy link
Contributor Author

@zimulala @winkyao

@codecov
Copy link

codecov bot commented Apr 26, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@4cf3630). Click here to learn what that means.
The diff coverage is n/a.

@@             Coverage Diff             @@
##             master     #10281   +/-   ##
===========================================
  Coverage          ?   77.6715%           
===========================================
  Files             ?        411           
  Lines             ?      85447           
  Branches          ?          0           
===========================================
  Hits              ?      66368           
  Misses            ?      14118           
  Partials          ?       4961

@@ -157,7 +157,9 @@ func (b *PlanBuilder) buildResultSetNode(node ast.ResultSetNode) (p LogicalPlan,
col.OrigTblName = col.TblName
if x.AsName.L != "" {
col.TblName = x.AsName
col.DBName = model.NewCIStr("")
if b.ctx.GetSessionVars().CurrentDB == col.DBName.L {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment here? Why should we check the currentDB name and set DBName to empty string?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can put an example here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why we set col.DBName = model.NewCIStr("") here @zimulala
I should remove this line ... but it would make explain result (column name) change and affect many rows in the test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll remove this line... that's a better fix, anyway

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tiancaiamao
I am not sure, I just changed the name of DBName. This line of code was originally written like this.
PTAL @XuHuaiyu

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the reason may be this:
When a table has an alias name, this "virtual table" does not belong to any database, we thought the DBName should be blank.
But I think it seems ok to keep the DBName here.

@@ -157,7 +157,6 @@ func (b *PlanBuilder) buildResultSetNode(node ast.ResultSetNode) (p LogicalPlan,
col.OrigTblName = col.TblName
if x.AsName.L != "" {
col.TblName = x.AsName
col.DBName = model.NewCIStr("")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is the real change in this PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add an empty database name can fix the issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the visitInfo record is

db=""
table="t1"
user="test"

It doesn't match any privilege record in the cache, so privilege check fail.

@zz-jason

Copy link
Contributor Author

@tiancaiamao tiancaiamao Apr 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The db name is not set correctly...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The db name is set to "", and we should not set it to ""

@tiancaiamao
Copy link
Contributor Author

PTAL @winkyao @zimulala @shenli

Copy link
Contributor

@winkyao winkyao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

├─TableReader_41 428.32 root data:Selection_40
│ └─Selection_40 428.32 cop eq(dt.bm, 0), eq(dt.pt, "ios"), gt(dt.t, 1478185592), not(isnull(dt.dic))
│ └─Selection_40 428.32 cop eq(test.dt.bm, 0), eq(test.dt.pt, "ios"), gt(test.dt.t, 1478185592), not(isnull(test.dt.dic))
│ └─TableScan_39 2000.00 cop table:dt, range:[0,+inf], keep order:false
Copy link
Contributor

@zimulala zimulala Apr 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it dt is alias name? If it's true, it is called dt here, but it's called test.dt on line 165. Is this a bit confused?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean we should use test.dt in line 166? Currently, we do not print database name for PhysicalTableScan.

func (p *PhysicalTableScan) ExplainInfo() string {
    buffer := bytes.NewBufferString("")
    tblName := p.Table.Name.O
    if p.TableAsName != nil && p.TableAsName.O != "" {
        tblName = p.TableAsName.O
    }
    fmt.Fprintf(buffer, "table:%s", tblName)
    ...
}

If needed, we can print DBName as well, since it is recorded in PhysicalTableScan.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eurekaka
No, I want to say if this situation will make you feel troubled.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think it is not bothering since we merely meet queries where 2 tables share same name but from different databases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

Copy link
Contributor

@zimulala zimulala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zimulala
Copy link
Contributor

/run-all-tests

@zimulala zimulala added the status/LGT2 Indicates that a PR has LGTM 2. label Apr 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/privilege status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants