// Copyright 2016 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. package executor_test import ( "fmt" "strings" . "github.com/pingcap/check" "github.com/pingcap/tidb" "github.com/pingcap/tidb/context" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/terror" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/testkit" "github.com/pingcap/tidb/util/testleak" ) func (s *testSuite) TestCharsetDatabase(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) testSQL := `create database if not exists cd_test_utf8 CHARACTER SET utf8 COLLATE utf8_bin;` tk.MustExec(testSQL) testSQL = `create database if not exists cd_test_latin1 CHARACTER SET latin1 COLLATE latin1_swedish_ci;` tk.MustExec(testSQL) testSQL = `use cd_test_utf8;` tk.MustExec(testSQL) tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows("utf8")) tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows("utf8_bin")) testSQL = `use cd_test_latin1;` tk.MustExec(testSQL) tk.MustQuery(`select @@character_set_database;`).Check(testkit.Rows("latin1")) tk.MustQuery(`select @@collation_database;`).Check(testkit.Rows("latin1_swedish_ci")) } func (s *testSuite) TestDo(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) tk.MustExec("do 1, @a:=1") tk.MustQuery("select @a").Check(testkit.Rows("1")) } func (s *testSuite) TestTransaction(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) tk.MustExec("begin") ctx := tk.Se.(context.Context) c.Assert(inTxn(ctx), IsTrue) tk.MustExec("commit") c.Assert(inTxn(ctx), IsFalse) tk.MustExec("begin") c.Assert(inTxn(ctx), IsTrue) tk.MustExec("rollback") c.Assert(inTxn(ctx), IsFalse) // Test that begin implicitly commits previous transaction. tk.MustExec("use test") tk.MustExec("create table txn (a int)") tk.MustExec("begin") tk.MustExec("insert txn values (1)") tk.MustExec("begin") tk.MustExec("rollback") tk.MustQuery("select * from txn").Check(testkit.Rows("1")) // Test that DDL implicitly commits previous transaction. tk.MustExec("begin") tk.MustExec("insert txn values (2)") tk.MustExec("create table txn2 (a int)") tk.MustExec("rollback") tk.MustQuery("select * from txn").Check(testkit.Rows("1", "2")) } func inTxn(ctx context.Context) bool { return (ctx.GetSessionVars().Status & mysql.ServerStatusInTrans) > 0 } func (s *testSuite) TestUser(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) // Make sure user test not in mysql.User. result := tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test" and Host="localhost"`) result.Check(nil) // Create user test. createUserSQL := `CREATE USER 'test'@'localhost' IDENTIFIED BY '123';` tk.MustExec(createUserSQL) // Make sure user test in mysql.User. result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test" and Host="localhost"`) rowStr := fmt.Sprintf("%v", []byte(util.EncodePassword("123"))) result.Check(testkit.Rows(rowStr)) // Create duplicate user with IfNotExists will be success. createUserSQL = `CREATE USER IF NOT EXISTS 'test'@'localhost' IDENTIFIED BY '123';` tk.MustExec(createUserSQL) // Create duplicate user without IfNotExists will cause error. createUserSQL = `CREATE USER 'test'@'localhost' IDENTIFIED BY '123';` _, err := tk.Exec(createUserSQL) c.Check(err, NotNil) dropUserSQL := `DROP USER IF EXISTS 'test'@'localhost' ;` tk.MustExec(dropUserSQL) // Create user test. createUserSQL = `CREATE USER 'test1'@'localhost';` tk.MustExec(createUserSQL) // Make sure user test in mysql.User. result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test1" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword(""))) result.Check(testkit.Rows(rowStr)) dropUserSQL = `DROP USER IF EXISTS 'test1'@'localhost' ;` tk.MustExec(dropUserSQL) // Test alter user. createUserSQL = `CREATE USER 'test1'@'localhost' IDENTIFIED BY '123', 'test2'@'localhost' IDENTIFIED BY '123', 'test3'@'localhost' IDENTIFIED BY '123';` tk.MustExec(createUserSQL) alterUserSQL := `ALTER USER 'test1'@'localhost' IDENTIFIED BY '111';` tk.MustExec(alterUserSQL) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test1" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("111"))) result.Check(testkit.Rows(rowStr)) alterUserSQL = `ALTER USER IF EXISTS 'test2'@'localhost' IDENTIFIED BY '222', 'test_not_exist'@'localhost' IDENTIFIED BY '1';` _, err = tk.Exec(alterUserSQL) c.Check(err, NotNil) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test2" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("222"))) result.Check(testkit.Rows(rowStr)) alterUserSQL = `ALTER USER IF EXISTS'test_not_exist'@'localhost' IDENTIFIED BY '1', 'test3'@'localhost' IDENTIFIED BY '333';` _, err = tk.Exec(alterUserSQL) c.Check(err, NotNil) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test3" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("333"))) result.Check(testkit.Rows(rowStr)) // Test alter user user(). alterUserSQL = `ALTER USER USER() IDENTIFIED BY '1';` _, err = tk.Exec(alterUserSQL) c.Check(err, NotNil) tk.Se, err = tidb.CreateSession(s.store) c.Check(err, IsNil) ctx := tk.Se.(context.Context) ctx.GetSessionVars().User = "test1@localhost" tk.MustExec(alterUserSQL) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="test1" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("1"))) result.Check(testkit.Rows(rowStr)) dropUserSQL = `DROP USER 'test1'@'localhost', 'test2'@'localhost', 'test3'@'localhost';` tk.MustExec(dropUserSQL) // Test drop user if exists. createUserSQL = `CREATE USER 'test1'@'localhost', 'test3'@'localhost';` tk.MustExec(createUserSQL) dropUserSQL = `DROP USER IF EXISTS 'test1'@'localhost', 'test2'@'localhost', 'test3'@'localhost' ;` tk.MustExec(dropUserSQL) // Test negative cases without IF EXISTS. createUserSQL = `CREATE USER 'test1'@'localhost', 'test3'@'localhost';` tk.MustExec(createUserSQL) dropUserSQL = `DROP USER 'test1'@'localhost', 'test2'@'localhost', 'test3'@'localhost';` _, err = tk.Exec(dropUserSQL) c.Check(err, NotNil) dropUserSQL = `DROP USER 'test3'@'localhost';` _, err = tk.Exec(dropUserSQL) c.Check(err, NotNil) dropUserSQL = `DROP USER 'test1'@'localhost';` _, err = tk.Exec(dropUserSQL) c.Check(err, NotNil) // Test positive cases without IF EXISTS. createUserSQL = `CREATE USER 'test1'@'localhost', 'test3'@'localhost';` tk.MustExec(createUserSQL) dropUserSQL = `DROP USER 'test1'@'localhost', 'test3'@'localhost';` tk.MustExec(dropUserSQL) } func (s *testSuite) TestSetPwd(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) createUserSQL := `CREATE USER 'testpwd'@'localhost' IDENTIFIED BY '';` tk.MustExec(createUserSQL) result := tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="testpwd" and Host="localhost"`) rowStr := fmt.Sprintf("%v", []byte("")) result.Check(testkit.Rows(rowStr)) // set password for tk.MustExec(`SET PASSWORD FOR 'testpwd'@'localhost' = 'password';`) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="testpwd" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("password"))) result.Check(testkit.Rows(rowStr)) // set password setPwdSQL := `SET PASSWORD = 'pwd'` // Session user is empty. _, err := tk.Exec(setPwdSQL) c.Check(err, NotNil) tk.Se, err = tidb.CreateSession(s.store) c.Check(err, IsNil) ctx := tk.Se.(context.Context) ctx.GetSessionVars().User = "testpwd1@localhost" // Session user doesn't exist. _, err = tk.Exec(setPwdSQL) c.Check(terror.ErrorEqual(err, executor.ErrPasswordNoMatch), IsTrue) // normal ctx.GetSessionVars().User = "testpwd@localhost" tk.MustExec(setPwdSQL) result = tk.MustQuery(`SELECT Password FROM mysql.User WHERE User="testpwd" and Host="localhost"`) rowStr = fmt.Sprintf("%v", []byte(util.EncodePassword("pwd"))) result.Check(testkit.Rows(rowStr)) } func (s *testSuite) TestAnalyzeTable(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") tk.MustExec("drop table if exists t1") tk.MustExec("create table t1 (a int)") tk.MustExec("create index ind_a on t1 (a)") tk.MustExec("insert into t1 (a) values (1)") result := tk.MustQuery("explain select * from t1 where t1.a = 1") rowStr := fmt.Sprintf("%s", result.Rows()) c.Check(strings.Split(rowStr, "{")[0], Equals, "[[IndexScan_5 ") tk.MustExec("analyze table t1") result = tk.MustQuery("explain select * from t1 where t1.a = 1") rowStr = fmt.Sprintf("%s", result.Rows()) c.Check(strings.Split(rowStr, "{")[0], Equals, "[[TableScan_4 ") }