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

Shenli/set password #195

Merged
merged 4 commits into from
Sep 20, 2015
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions mysqldef/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,13 @@ const (
const (
AuthName = "mysql_native_password"
)

// mysql database and tables
Copy link
Member

Choose a reason for hiding this comment

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

MySQL
End of .

const (
// MySQLDB is the name of mysql system database.
MySQLDB = "mysql"
// UserTable is the table in mysql db contains user info.
UserTable = "User"

CreateUserTable = "CREATE TABLE if not exists mysql.user (Host CHAR(64), User CHAR(16), Password CHAR(41), PRIMARY KEY (Host, User));"
)
11 changes: 8 additions & 3 deletions parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import (
any "ANY"
as "AS"
asc "ASC"
at "AT"
autoIncrement "AUTO_INCREMENT"
avg "AVG"
begin "BEGIN"
Expand Down Expand Up @@ -3009,13 +3010,17 @@ UserVariable:
}

Username:
Identifier
stringLit "AT" stringLit
{
$$ = $1.(string)
$$ = $1.(string) + "@" + $3.(string)
}

PasswordOpt:
"PASSWORD" '(' AuthString ')'
stringLit
{
$$ = $1.(string)
}
| "PASSWORD" '(' AuthString ')'
{
$$ = $3.(string)
}
Expand Down
3 changes: 3 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ func (s *testParserSuite) TestParser0(c *C) {
// SET CHARACTER SET
{"SET CHARACTER SET utf8mb4;", true},
{"SET CHARACTER SET 'utf8mb4';", true},
// Set password
{"SET PASSWORD = 'password';", true},
{"SET PASSWORD FOR 'shenli'@'localhost' = 'password';", true},
Copy link
Member

Choose a reason for hiding this comment

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

I think root may be better than your name......


// qualified select
{"SELECT a.b.c FROM t", true},
Expand Down
1 change: 1 addition & 0 deletions parser/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ sys_var "@@"(({global}".")|({session}".")|{local}".")?{ident}
">>" return rsh
"<=>" return nulleq

"@" return at
"?" return placeholder

{abs} lval.item = string(l.val)
Expand Down
25 changes: 17 additions & 8 deletions stmt/stmts/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/ngaut/log"
. "github.com/pingcap/check"
"github.com/pingcap/tidb"
mysql "github.com/pingcap/tidb/mysqldef"
)

func TestT(t *testing.T) {
Expand All @@ -32,18 +33,20 @@ var _ = Suite(&testStmtSuite{})
type testStmtSuite struct {
dbName string

testDB *sql.DB
createDBSql string
dropDBSql string
useDBSql string
createTableSql string
insertSql string
selectSql string
testDB *sql.DB
createDBSql string
dropDBSql string
useDBSql string
createTableSql string
Copy link
Member

Choose a reason for hiding this comment

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

Replace Sql to Text would be better.

Copy link
Member Author

Choose a reason for hiding this comment

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

They are all SQL statements.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, SQL is structured query language, it doesn't means text.
But we do mean text here.

insertSql string
selectSql string
createMySQLDBSQL string
createMySQLUserTableSQL string
}

func (s *testStmtSuite) SetUpTest(c *C) {
log.SetLevelByString("error")
s.dbName = "test"
s.dbName = "teststmts"
var err error
s.testDB, err = sql.Open(tidb.DriverName, tidb.EngineGoLevelDBMemory+"/"+s.dbName+"/"+s.dbName)
c.Assert(err, IsNil)
Expand All @@ -59,6 +62,12 @@ func (s *testStmtSuite) SetUpTest(c *C) {
s.selectSql = `SELECT * from test limit 2;`
mustExec(c, s.testDB, s.createDBSql)
mustExec(c, s.testDB, s.useDBSql)

s.createMySQLDBSQL = fmt.Sprintf("create database if not exists %s;", mysql.MySQLDB)
Copy link
Member

Choose a reason for hiding this comment

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

MySQLDBSQL looks wired. Could you rename createMySQLDBSQL to createDBText

Copy link
Member Author

Choose a reason for hiding this comment

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

MySQL is the DB name. This is the system db. How about createSystemDB?

Copy link
Member

Choose a reason for hiding this comment

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

createSystemDB is ok for me :)

s.createMySQLUserTableSQL = mysql.CreateUserTable

mustExec(c, s.testDB, s.createMySQLDBSQL)
mustExec(c, s.testDB, s.createMySQLUserTableSQL)
}

func (s *testStmtSuite) TearDownTest(c *C) {
Expand Down
33 changes: 31 additions & 2 deletions stmt/stmts/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ import (
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/expression/expressions"
"github.com/pingcap/tidb/model"
mysql "github.com/pingcap/tidb/mysqldef"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/rset"
"github.com/pingcap/tidb/rset/rsets"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/stmt"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/util/format"
)

Expand Down Expand Up @@ -230,6 +235,30 @@ func (s *SetPwdStmt) SetText(text string) {

// Exec implements the stmt.Statement Exec interface.
func (s *SetPwdStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) {
// TODO: finish this
return nil, nil
// If len(s.User) == 0, use CURRENT_USER()
strs := strings.Split(s.User, "@")
userName := strs[0]
host := strs[1]
// Update mysql.user
r := &rsets.JoinRset{
Left: &rsets.TableSource{
Source: table.Ident{
Name: model.NewCIStr(mysql.UserTable),
Schema: model.NewCIStr(mysql.MySQLDB),
},
},
}
asgn := expressions.Assignment{
ColName: "Password",
Expr: expressions.Value{Val: s.Password},
}
nameMatch := expressions.NewBinaryOperation(opcode.EQ, &expressions.Ident{CIStr: model.NewCIStr("User")}, &expressions.Value{Val: userName})
hostMatch := expressions.NewBinaryOperation(opcode.EQ, &expressions.Ident{CIStr: model.NewCIStr("Host")}, &expressions.Value{Val: host})
Copy link
Member

Choose a reason for hiding this comment

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

Here not check name or host match, how about nameExpr and hostExpr?

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean check the validation of name/host?
The validation will be checked in update.Exec(). The privilege check will be coming later.

Copy link
Member

Choose a reason for hiding this comment

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

I only mean whether the variable names use nameExpr and hostExpr are better, for nameMatch and nameMatch sound like boolean variables.

Copy link
Member

Choose a reason for hiding this comment

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

I only mean whether the variable names use nameExpr and hostExpr are better, for nameMatch and nameMatch sound like boolean variables.

Copy link
Member Author

Choose a reason for hiding this comment

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

They are boolean expressions. For nameMatch means if "User" equals userName.

where := expressions.NewBinaryOperation(opcode.AndAnd, nameMatch, hostMatch)
st := &UpdateStmt{
TableRefs: r,
List: []expressions.Assignment{asgn},
Where: where,
}
return st.Exec(ctx)
Copy link
Member

Choose a reason for hiding this comment

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

Btw, how do u think of building an update sql to excute it?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't want to call parser for the second time.

Copy link
Member

Choose a reason for hiding this comment

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

Gotcha.

}
36 changes: 22 additions & 14 deletions stmt/stmts/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,21 +139,29 @@ func (s *testStmtSuite) TestSetCharsetStmt(c *C) {
}

func (s *testStmtSuite) TestSetPwdStmt(c *C) {
// Mock SetPwdStmt.
testStmt := &stmts.SetPwdStmt{
User: "user",
Password: "password",
}

testStmt.SetText(`SET PASSWORD FOR 'user' = PASSWORD('password');`)
tx := mustBegin(c, s.testDB)
tx.Query(`INSERT INTO mysql.User VALUES ("localhost", "root", ""), ("127.0.0.1", "root", "")`)
rows, err := tx.Query(`SELECT Password FROM mysql.User WHERE User="root" and Host="localhost"`)
c.Assert(err, IsNil)
rows.Next()
var pwd string
rows.Scan(&pwd)
c.Assert(pwd, Equals, "")
c.Assert(rows.Next(), IsFalse)
rows.Close()
mustCommit(c, tx)

c.Assert(testStmt.IsDDL(), IsFalse)
c.Assert(len(testStmt.OriginText()), Greater, 0)
tx = mustBegin(c, s.testDB)
tx.Query(`SET PASSWORD FOR 'root'@'localhost' = 'password';`)
mustCommit(c, tx)

_, err := testStmt.Exec(nil)
tx = mustBegin(c, s.testDB)
rows, err = tx.Query(`SELECT Password FROM mysql.User WHERE User="root" and Host="localhost"`)
c.Assert(err, IsNil)

mf := newMockFormatter()
testStmt.Explain(nil, mf)
c.Assert(mf.Len(), Greater, 0)
rows.Next()
rows.Scan(&pwd)
c.Assert(pwd, Equals, "password")
c.Assert(rows.Next(), IsFalse)
rows.Close()
mustCommit(c, tx)
}