Files
tidb/ddl/sequence_test.go

266 lines
12 KiB
Go

// Copyright 2019 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 ddl_test
import (
. "github.com/pingcap/check"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/terror"
"github.com/pingcap/tidb/ddl"
"github.com/pingcap/tidb/session"
"github.com/pingcap/tidb/util/testkit"
)
var _ = Suite(&testSequenceSuite{&testDBSuite{}})
type testSequenceSuite struct{ *testDBSuite }
func (s *testSequenceSuite) TestCreateSequence(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.tk.MustExec("use test")
s.tk.MustGetErrCode("create sequence `seq `", mysql.ErrWrongTableName)
// maxvalue should be larger than minvalue.
s.tk.MustGetErrCode("create sequence seq maxvalue 1 minvalue 2", mysql.ErrSequenceInvalidData)
// maxvalue should be larger than minvalue.
s.tk.MustGetErrCode("create sequence seq maxvalue 1 minvalue 1", mysql.ErrSequenceInvalidData)
// maxvalue shouldn't be equal to MaxInt64.
s.tk.MustGetErrCode("create sequence seq maxvalue 9223372036854775807 minvalue 1", mysql.ErrSequenceInvalidData)
// TODO : minvalue shouldn't be equal to MinInt64.
// maxvalue should be larger than start.
s.tk.MustGetErrCode("create sequence seq maxvalue 1 start with 2", mysql.ErrSequenceInvalidData)
// cacheVal should be less than (math.MaxInt64-maxIncrement)/maxIncrement.
s.tk.MustGetErrCode("create sequence seq increment 100000 cache 922337203685477", mysql.ErrSequenceInvalidData)
// test unsupported table option in sequence.
s.tk.MustGetErrCode("create sequence seq CHARSET=utf8", mysql.ErrSequenceUnsupportedTableOption)
_, err := s.tk.Exec("create sequence seq comment=\"test\"")
c.Assert(err, IsNil)
sequenceTable := testGetTableByName(c, s.s, "test", "seq")
c.Assert(sequenceTable.Meta().IsSequence(), Equals, true)
c.Assert(sequenceTable.Meta().Sequence.Increment, Equals, model.DefaultSequenceIncrementValue)
c.Assert(sequenceTable.Meta().Sequence.Start, Equals, model.DefaultPositiveSequenceStartValue)
c.Assert(sequenceTable.Meta().Sequence.MinValue, Equals, model.DefaultPositiveSequenceMinValue)
c.Assert(sequenceTable.Meta().Sequence.MaxValue, Equals, model.DefaultPositiveSequenceMaxValue)
c.Assert(sequenceTable.Meta().Sequence.Cache, Equals, true)
c.Assert(sequenceTable.Meta().Sequence.CacheValue, Equals, model.DefaultSequenceCacheValue)
c.Assert(sequenceTable.Meta().Sequence.Cycle, Equals, false)
c.Assert(sequenceTable.Meta().Sequence.Order, Equals, false)
// Test create privilege.
s.tk.MustExec("create user myuser@localhost")
s.tk.MustExec("flush privileges")
tk1 := testkit.NewTestKit(c, s.store)
se, err := session.CreateSession4Test(s.store)
c.Assert(err, IsNil)
c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue)
tk1.Se = se
// grant the myuser the access to database test.
s.tk.MustExec("grant select on test.* to 'myuser'@'localhost'")
s.tk.MustExec("flush privileges")
tk1.MustExec("use test")
_, err = tk1.Exec("create sequence my_seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[planner:1142]CREATE command denied to user 'localhost'@'myuser' for table 'my_seq'")
}
func (s *testSequenceSuite) TestDropSequence(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.tk.MustExec("use test")
s.tk.MustExec("drop sequence if exists seq")
// Test sequence is unknown.
s.tk.MustGetErrCode("drop sequence seq", mysql.ErrUnknownSequence)
// Test non-existed sequence can't drop successfully.
s.tk.MustExec("create sequence seq")
_, err := s.tk.Exec("drop sequence seq, seq2")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'test.seq2'")
// Test the specified object is not sequence.
s.tk.MustExec("create table seq3 (a int)")
_, err = s.tk.Exec("drop sequence seq3")
c.Assert(err, NotNil)
c.Assert(terror.ErrorEqual(err, ddl.ErrWrongObject), IsTrue)
// Test schema is not exist.
_, err = s.tk.Exec("drop sequence unknown.seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'unknown.seq'")
// Test drop sequence successfully.
s.tk.MustExec("create sequence seq")
_, err = s.tk.Exec("drop sequence seq")
c.Assert(err, IsNil)
_, err = s.tk.Exec("drop sequence seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[schema:4139]Unknown SEQUENCE: 'test.seq'")
// Test drop table when the object is a sequence.
s.tk.MustExec("create sequence seq")
_, err = s.tk.Exec("drop table seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.seq'")
// Test drop view when the object is a sequence.
_, err = s.tk.Exec("drop view seq")
c.Assert(err, NotNil)
c.Assert(terror.ErrorEqual(err, ddl.ErrWrongObject), IsTrue)
s.tk.MustExec("drop sequence seq")
// Test drop privilege.
s.tk.MustExec("drop user if exists myuser@localhost")
s.tk.MustExec("create user myuser@localhost")
s.tk.MustExec("flush privileges")
tk1 := testkit.NewTestKit(c, s.store)
se, err := session.CreateSession4Test(s.store)
c.Assert(err, IsNil)
c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue)
tk1.Se = se
// grant the myuser the access to database test.
s.tk.MustExec("create sequence my_seq")
s.tk.MustExec("grant select on test.* to 'myuser'@'localhost'")
s.tk.MustExec("flush privileges")
tk1.MustExec("use test")
_, err = tk1.Exec("drop sequence my_seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[planner:1142]DROP command denied to user 'localhost'@'myuser' for table 'my_seq'")
}
func (s *testSequenceSuite) TestShowCreateSequence(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.tk.MustExec("use test")
s.tk.MustExec("drop table if exists t")
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create table t(a int)")
s.tk.MustExec("create sequence seq")
// Test show privilege.
s.tk.MustExec("drop user if exists myuser@localhost")
s.tk.MustExec("create user myuser@localhost")
s.tk.MustExec("flush privileges")
tk1 := testkit.NewTestKit(c, s.store)
se, err := session.CreateSession4Test(s.store)
c.Assert(err, IsNil)
c.Assert(se.Auth(&auth.UserIdentity{Username: "myuser", Hostname: "localhost"}, nil, nil), IsTrue)
tk1.Se = se
// Grant the myuser the access to table t in database test, but sequence seq.
s.tk.MustExec("grant select on test.t to 'myuser'@'localhost'")
s.tk.MustExec("flush privileges")
tk1.MustExec("use test")
tk1.MustExec("show create table t")
_, err = tk1.Exec("show create sequence seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[planner:1142]SHOW command denied to user 'myuser'@'localhost' for table 'seq'")
// Grant the myuser the access to sequence seq in database test.
s.tk.MustExec("grant select on test.seq to 'myuser'@'localhost'")
s.tk.MustExec("flush privileges")
tk1.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB"))
// Test show sequence detail.
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq start 10")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 10 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq minvalue 0")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 0 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq maxvalue 100")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 100 increment by 1 cache 1000 nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq increment = -2")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with -1 minvalue -9223372036854775807 maxvalue -1 increment by -2 cache 1000 nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq nocache")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq cycle")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 cycle ENGINE=InnoDB"))
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq comment=\"ccc\"")
s.tk.MustQuery("show create sequence seq").Check(testkit.Rows("seq CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB COMMENT='ccc'"))
// Test show create sequence with a normal table.
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create table seq (a int)")
err = s.tk.QueryToErr("show create sequence seq")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[executor:1347]'test.seq' is not SEQUENCE")
s.tk.MustExec("drop table if exists seq")
// Test use the show create sequence result to create sequence.
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec("create sequence seq")
showString := s.tk.MustQuery("show create sequence seq").Rows()[0][1].(string)
s.tk.MustExec("drop sequence if exists seq")
s.tk.MustExec(showString)
}
func (s *testSequenceSuite) TestSequenceAsDefaultValue(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.tk.MustExec("use test")
s.tk.MustExec("create sequence seq")
// test the use sequence's nextval as default.
s.tk.MustExec("create table t1 (a int default next value for seq)")
s.tk.MustGetErrMsg("create table t2 (a char(1) default next value for seq)", "[ddl:8228]Unsupported sequence default value for column type 'a'")
s.tk.MustExec("create table t3 (a int default nextval(seq))")
s.tk.MustExec("create table t4 (a int)")
s.tk.MustExec("alter table t4 alter column a set default (next value for seq)")
s.tk.MustExec("alter table t4 alter column a set default (nextval(seq))")
s.tk.MustExec("create table t5 (a char(1))")
s.tk.MustGetErrMsg("alter table t5 alter column a set default (next value for seq)", "[ddl:8228]Unsupported sequence default value for column type 'a'")
s.tk.MustGetErrMsg("alter table t5 alter column a set default (nextval(seq))", "[ddl:8228]Unsupported sequence default value for column type 'a'")
s.tk.MustGetErrMsg("alter table t5 add column b char(1) default next value for seq", "[ddl:8228]Unsupported sequence default value for column type 'b'")
s.tk.MustExec("alter table t5 add column b int default nextval(seq)")
}