Files
tidb/util/kvencoder/kv_encoder_test.go
2019-06-27 13:51:16 +08:00

734 lines
22 KiB
Go

// Copyright 2017 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 kvenc
import (
"bytes"
"fmt"
"strconv"
"testing"
"time"
"github.com/pingcap/tidb/meta/autoid"
"github.com/pingcap/tidb/store/mockstore"
. "github.com/pingcap/check"
"github.com/pingcap/errors"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/session"
"github.com/pingcap/tidb/sessionctx/stmtctx"
"github.com/pingcap/tidb/structure"
"github.com/pingcap/tidb/tablecodec"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/util/testleak"
)
var _ = Suite(&testKvEncoderSuite{})
func TestT(t *testing.T) {
TestingT(t)
}
func newStoreWithBootstrap() (kv.Storage, *domain.Domain, error) {
store, err := mockstore.NewMockTikvStore()
if err != nil {
return nil, nil, errors.Trace(err)
}
session.SetSchemaLease(0)
session.DisableStats4Test()
dom, err := session.BootstrapSession(store)
return store, dom, errors.Trace(err)
}
type testKvEncoderSuite struct {
store kv.Storage
dom *domain.Domain
}
func (s *testKvEncoderSuite) cleanEnv(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
r := tk.MustQuery("show tables")
for _, tb := range r.Rows() {
tableName := tb[0]
tk.MustExec(fmt.Sprintf("drop table %v", tableName))
}
}
func (s *testKvEncoderSuite) SetUpSuite(c *C) {
testleak.BeforeTest()
store, dom, err := newStoreWithBootstrap()
c.Assert(err, IsNil)
s.store = store
s.dom = dom
}
func (s *testKvEncoderSuite) TearDownSuite(c *C) {
s.dom.Close()
s.store.Close()
testleak.AfterTest(c)()
}
func getExpectKvPairs(tkExpect *testkit.TestKit, sql string) []KvPair {
tkExpect.MustExec("begin")
tkExpect.MustExec(sql)
kvPairsExpect := make([]KvPair, 0)
txn, err := tkExpect.Se.Txn(true)
if err != nil {
return nil
}
kv.WalkMemBuffer(txn.GetMemBuffer(), func(k kv.Key, v []byte) error {
kvPairsExpect = append(kvPairsExpect, KvPair{Key: k, Val: v})
return nil
})
tkExpect.MustExec("rollback")
return kvPairsExpect
}
type testCase struct {
sql string
// expectEmptyValCnt only check if expectEmptyValCnt > 0
expectEmptyValCnt int
// expectKvCnt only check if expectKvCnt > 0
expectKvCnt int
expectAffectedRows int
}
func (s *testKvEncoderSuite) runTestSQL(c *C, tkExpect *testkit.TestKit, encoder KvEncoder, cases []testCase, tableID int64) {
for _, ca := range cases {
comment := fmt.Sprintf("sql:%v", ca.sql)
kvPairs, affectedRows, err := encoder.Encode(ca.sql, tableID)
c.Assert(err, IsNil, Commentf(comment))
if ca.expectAffectedRows > 0 {
c.Assert(affectedRows, Equals, uint64(ca.expectAffectedRows))
}
kvPairsExpect := getExpectKvPairs(tkExpect, ca.sql)
c.Assert(len(kvPairs), Equals, len(kvPairsExpect), Commentf(comment))
if ca.expectKvCnt > 0 {
c.Assert(len(kvPairs), Equals, ca.expectKvCnt, Commentf(comment))
}
emptyValCount := 0
for i, row := range kvPairs {
expectKey := kvPairsExpect[i].Key
if bytes.HasPrefix(row.Key, tablecodec.TablePrefix()) {
expectKey = tablecodec.ReplaceRecordKeyTableID(expectKey, tableID)
}
c.Assert(bytes.Compare(row.Key, expectKey), Equals, 0, Commentf(comment))
c.Assert(bytes.Compare(row.Val, kvPairsExpect[i].Val), Equals, 0, Commentf(comment))
if len(row.Val) == 0 {
emptyValCount++
}
}
if ca.expectEmptyValCnt > 0 {
c.Assert(emptyValCount, Equals, ca.expectEmptyValCnt, Commentf(comment))
}
}
}
func (s *testKvEncoderSuite) TestCustomDatabaseHandle(c *C) {
dbname := "tidb"
tkExpect := testkit.NewTestKit(c, s.store)
tkExpect.MustExec("create database if not exists " + dbname)
tkExpect.MustExec("use " + dbname)
encoder, err := New(dbname, nil)
c.Assert(err, IsNil)
defer encoder.Close()
var tableID int64 = 123
schemaSQL := "create table tis (id int auto_increment, a char(10), primary key(id))"
tkExpect.MustExec(schemaSQL)
err = encoder.ExecDDLSQL(schemaSQL)
c.Assert(err, IsNil)
sqls := []testCase{
{"insert into tis (a) values('test')", 0, 1, 1},
{"insert into tis (a) values('test'), ('test1')", 0, 2, 2},
}
s.runTestSQL(c, tkExpect, encoder, sqls, tableID)
}
func (s *testKvEncoderSuite) TestInsertPkIsHandle(c *C) {
tkExpect := testkit.NewTestKit(c, s.store)
tkExpect.MustExec("use test")
var tableID int64 = 1
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
tkExpect.MustExec("drop table if exists t")
schemaSQL := "create table t(id int auto_increment, a char(10), primary key(id))"
tkExpect.MustExec(schemaSQL)
err = encoder.ExecDDLSQL(schemaSQL)
c.Assert(err, IsNil)
sqls := []testCase{
{"insert into t values(1, 'test');", 0, 1, 1},
{"insert into t(a) values('test')", 0, 1, 1},
{"insert into t(a) values('test'), ('test1')", 0, 2, 2},
{"insert into t(id, a) values(3, 'test')", 0, 1, 1},
{"insert into t values(1000000, 'test')", 0, 1, 1},
{"insert into t(a) values('test')", 0, 1, 1},
{"insert into t(id, a) values(4, 'test')", 0, 1, 1},
}
s.runTestSQL(c, tkExpect, encoder, sqls, tableID)
tkExpect.MustExec("drop table if exists t1")
schemaSQL = "create table t1(id int auto_increment, a char(10), primary key(id), key a_idx(a))"
tkExpect.MustExec(schemaSQL)
err = encoder.ExecDDLSQL(schemaSQL)
c.Assert(err, IsNil)
tableID = 2
sqls = []testCase{
{"insert into t1 values(1, 'test');", 0, 2, 1},
{"insert into t1(a) values('test')", 0, 2, 1},
{"insert into t1(id, a) values(3, 'test')", 0, 2, 1},
{"insert into t1 values(1000000, 'test')", 0, 2, 1},
{"insert into t1(a) values('test')", 0, 2, 1},
{"insert into t1(id, a) values(4, 'test')", 0, 2, 1},
}
s.runTestSQL(c, tkExpect, encoder, sqls, tableID)
schemaSQL = `create table t2(
id int auto_increment,
a char(10),
b datetime default NULL,
primary key(id),
key a_idx(a),
unique b_idx(b))
`
tableID = 3
tkExpect.MustExec("drop table if exists t2")
tkExpect.MustExec(schemaSQL)
err = encoder.ExecDDLSQL(schemaSQL)
c.Assert(err, IsNil)
sqls = []testCase{
{"insert into t2(id, a) values(1, 'test')", 0, 3, 1},
{"insert into t2 values(2, 'test', '2017-11-27 23:59:59')", 0, 3, 1},
{"insert into t2 values(3, 'test', '2017-11-28 23:59:59')", 0, 3, 1},
}
s.runTestSQL(c, tkExpect, encoder, sqls, tableID)
}
type prepareTestCase struct {
sql string
formatSQL string
param []interface{}
}
func makePrepareTestCase(sql, formatSQL string, param ...interface{}) prepareTestCase {
return prepareTestCase{sql, formatSQL, param}
}
func (s *testKvEncoderSuite) TestPrepareEncode(c *C) {
alloc := NewAllocator()
encoder, err := New("test", alloc)
c.Assert(err, IsNil)
defer encoder.Close()
schemaSQL := "create table t(id int auto_increment, a char(10), primary key(id))"
err = encoder.ExecDDLSQL(schemaSQL)
c.Assert(err, IsNil)
cases := []prepareTestCase{
makePrepareTestCase("insert into t values(1, 'test')", "insert into t values(?, ?)", 1, "test"),
makePrepareTestCase("insert into t(a) values('test')", "insert into t(a) values(?)", "test"),
makePrepareTestCase("insert into t(a) values('test'), ('test1')", "insert into t(a) values(?), (?)", "test", "test1"),
makePrepareTestCase("insert into t(id, a) values(3, 'test')", "insert into t(id, a) values(?, ?)", 3, "test"),
}
tableID := int64(1)
for _, ca := range cases {
s.comparePrepareAndNormalEncode(c, alloc, tableID, encoder, ca.sql, ca.formatSQL, ca.param...)
}
}
func (s *testKvEncoderSuite) comparePrepareAndNormalEncode(c *C, alloc autoid.Allocator, tableID int64, encoder KvEncoder, sql, prepareFormat string, param ...interface{}) {
comment := fmt.Sprintf("sql:%v", sql)
baseID := alloc.Base()
kvPairsExpect, affectedRowsExpect, err := encoder.Encode(sql, tableID)
c.Assert(err, IsNil, Commentf(comment))
stmtID, err := encoder.PrepareStmt(prepareFormat)
c.Assert(err, IsNil, Commentf(comment))
alloc.(*Allocator).Reset(baseID)
kvPairs, affectedRows, err := encoder.EncodePrepareStmt(tableID, stmtID, param...)
c.Assert(err, IsNil, Commentf(comment))
c.Assert(affectedRows, Equals, affectedRowsExpect, Commentf(comment))
c.Assert(len(kvPairs), Equals, len(kvPairsExpect), Commentf(comment))
for i, kvPair := range kvPairs {
kvPairExpect := kvPairsExpect[i]
c.Assert(bytes.Compare(kvPair.Key, kvPairExpect.Key), Equals, 0, Commentf(comment))
c.Assert(bytes.Compare(kvPair.Val, kvPairExpect.Val), Equals, 0, Commentf(comment))
}
}
func (s *testKvEncoderSuite) TestInsertPkIsNotHandle(c *C) {
tkExpect := testkit.NewTestKit(c, s.store)
tkExpect.MustExec("use test")
var tableID int64 = 1
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
tkExpect.MustExec("drop table if exists t")
schemaSQL := `create table t(
id varchar(20),
a char(10),
primary key(id))`
tkExpect.MustExec(schemaSQL)
c.Assert(encoder.ExecDDLSQL(schemaSQL), IsNil)
sqls := []testCase{
{"insert into t values(1, 'test');", 0, 2, 1},
{"insert into t(id, a) values(2, 'test')", 0, 2, 1},
{"insert into t(id, a) values(3, 'test')", 0, 2, 1},
{"insert into t values(1000000, 'test')", 0, 2, 1},
{"insert into t(id, a) values(5, 'test')", 0, 2, 1},
{"insert into t(id, a) values(4, 'test')", 0, 2, 1},
{"insert into t(id, a) values(6, 'test'), (7, 'test'), (8, 'test')", 0, 6, 3},
}
s.runTestSQL(c, tkExpect, encoder, sqls, tableID)
}
func (s *testKvEncoderSuite) TestRetryWithAllocator(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
alloc := NewAllocator()
var tableID int64 = 1
encoder, err := New("test", alloc)
c.Assert(err, IsNil)
defer encoder.Close()
tk.MustExec("drop table if exists t")
schemaSQL := `create table t(
id int auto_increment,
a char(10),
primary key(id))`
tk.MustExec(schemaSQL)
c.Assert(encoder.ExecDDLSQL(schemaSQL), IsNil)
sqls := []string{
"insert into t(a) values('test');",
"insert into t(a) values('test'), ('1'), ('2'), ('3');",
"insert into t(id, a) values(1000000, 'test')",
"insert into t(id, a) values(5, 'test')",
"insert into t(id, a) values(4, 'test')",
}
for _, sql := range sqls {
baseID := alloc.Base()
kvPairs, _, err1 := encoder.Encode(sql, tableID)
c.Assert(err1, IsNil, Commentf("sql:%s", sql))
alloc.Reset(baseID)
retryKvPairs, _, err1 := encoder.Encode(sql, tableID)
c.Assert(err1, IsNil, Commentf("sql:%s", sql))
c.Assert(len(kvPairs), Equals, len(retryKvPairs))
for i, row := range kvPairs {
c.Assert(bytes.Compare(row.Key, retryKvPairs[i].Key), Equals, 0, Commentf(sql))
c.Assert(bytes.Compare(row.Val, retryKvPairs[i].Val), Equals, 0, Commentf(sql))
}
}
// specify id, it must be the same row
sql := "insert into t(id, a) values(5, 'test')"
kvPairs, _, err := encoder.Encode(sql, tableID)
c.Assert(err, IsNil, Commentf("sql:%s", sql))
retryKvPairs, _, err := encoder.Encode(sql, tableID)
c.Assert(err, IsNil, Commentf("sql:%s", sql))
c.Assert(len(kvPairs), Equals, len(retryKvPairs))
for i, row := range kvPairs {
c.Assert(bytes.Compare(row.Key, retryKvPairs[i].Key), Equals, 0, Commentf(sql))
c.Assert(bytes.Compare(row.Val, retryKvPairs[i].Val), Equals, 0, Commentf(sql))
}
tk.MustExec("drop table if exists t1")
schemaSQL = `create table t1(
id int auto_increment,
a char(10),
b char(10),
primary key(id),
KEY idx_a(a),
unique b_idx(b))`
tk.MustExec(schemaSQL)
c.Assert(encoder.ExecDDLSQL(schemaSQL), IsNil)
tableID = 2
sqls = []string{
"insert into t1(a, b) values('test', 'b1');",
"insert into t1(a, b) values('test', 'b2'), ('1', 'b3'), ('2', 'b4'), ('3', 'b5');",
"insert into t1(id, a, b) values(1000000, 'test', 'b6')",
"insert into t1(id, a, b) values(5, 'test', 'b7')",
"insert into t1(id, a, b) values(4, 'test', 'b8')",
"insert into t1(a, b) values('test', 'b9');",
}
for _, sql := range sqls {
baseID := alloc.Base()
kvPairs, _, err1 := encoder.Encode(sql, tableID)
c.Assert(err1, IsNil, Commentf("sql:%s", sql))
alloc.Reset(baseID)
retryKvPairs, _, err1 := encoder.Encode(sql, tableID)
c.Assert(err1, IsNil, Commentf("sql:%s", sql))
c.Assert(len(kvPairs), Equals, len(retryKvPairs))
for i, row := range kvPairs {
c.Assert(bytes.Compare(row.Key, retryKvPairs[i].Key), Equals, 0, Commentf(sql))
c.Assert(bytes.Compare(row.Val, retryKvPairs[i].Val), Equals, 0, Commentf(sql))
}
}
}
func (s *testKvEncoderSuite) TestAllocatorRebase(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
alloc := NewAllocator()
var tableID int64 = 1
encoder, err := New("test", alloc)
c.Assert(err, IsNil)
err = alloc.Rebase(tableID, 100, false)
c.Assert(err, IsNil)
defer encoder.Close()
c.Assert(alloc.Base(), Equals, int64(100))
schemaSQL := `create table t(
id int auto_increment,
a char(10),
primary key(id))`
tk.MustExec(schemaSQL)
c.Assert(encoder.ExecDDLSQL(schemaSQL), IsNil)
sql := "insert into t(id, a) values(1000, 'test')"
encoder.Encode(sql, tableID)
c.Assert(alloc.Base(), Equals, int64(1000))
sql = "insert into t(a) values('test')"
encoder.Encode(sql, tableID)
c.Assert(alloc.Base(), Equals, int64(1001))
sql = "insert into t(id, a) values(2000, 'test')"
encoder.Encode(sql, tableID)
c.Assert(alloc.Base(), Equals, int64(2000))
c.Assert(alloc.End(), Equals, int64(2000)+step)
nextID, err := alloc.NextGlobalAutoID(tableID)
c.Assert(err, IsNil)
c.Assert(nextID, Equals, int64(2000)+step+1)
}
func (s *testKvEncoderSuite) TestError(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
alloc := NewAllocator()
encoder, err := New("test", alloc)
c.Assert(err, IsNil)
defer encoder.Close()
_, err = New("", alloc)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, "*Incorrect database name ''")
err = encoder.ExecDDLSQL("x")
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, "*You have an error in your SQL syntax.*")
_, err = encoder.PrepareStmt("")
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, "*Can not prepare multiple statements")
_, _, err = encoder.EncodePrepareStmt(0, 0, 0)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, "*Prepared statement not found")
encoder = &kvEncoder{}
err = encoder.SetSystemVariable("", "")
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, ".*please new KvEncoder by kvencoder.New.*")
_, ok := encoder.GetSystemVariable("")
c.Assert(ok, IsFalse)
c.Assert(err, ErrorMatches, ".*please new KvEncoder by kvencoder.New.*")
}
func (s *testKvEncoderSuite) TestAllocatorRebaseSmaller(c *C) {
alloc := NewAllocator()
alloc.Rebase(1, 10, false)
c.Assert(alloc.Base(), Equals, int64(10))
alloc.Rebase(1, 100, false)
c.Assert(alloc.Base(), Equals, int64(100))
alloc.Rebase(1, 1, false)
c.Assert(alloc.Base(), Equals, int64(100))
alloc.Reset(1)
c.Assert(alloc.Base(), Equals, int64(1))
}
func (s *testKvEncoderSuite) TestSimpleKeyEncode(c *C) {
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
schemaSQL := `create table t(
id int auto_increment,
a char(10),
b char(10) default NULL,
primary key(id),
key a_idx(a))
`
encoder.ExecDDLSQL(schemaSQL)
tableID := int64(1)
indexID := int64(1)
sql := "insert into t values(1, 'a', 'b')"
kvPairs, affectedRows, err := encoder.Encode(sql, tableID)
c.Assert(err, IsNil)
c.Assert(len(kvPairs), Equals, 2)
c.Assert(affectedRows, Equals, uint64(1))
tablePrefix := tablecodec.GenTableRecordPrefix(tableID)
handle := int64(1)
expectRecordKey := tablecodec.EncodeRecordKey(tablePrefix, handle)
sc := &stmtctx.StatementContext{TimeZone: time.Local}
indexPrefix := tablecodec.EncodeTableIndexPrefix(tableID, indexID)
expectIdxKey := make([]byte, 0)
expectIdxKey = append(expectIdxKey, []byte(indexPrefix)...)
expectIdxKey, err = codec.EncodeKey(sc, expectIdxKey, types.NewDatum([]byte("a")))
c.Assert(err, IsNil)
expectIdxKey, err = codec.EncodeKey(sc, expectIdxKey, types.NewDatum(handle))
c.Assert(err, IsNil)
for _, row := range kvPairs {
tID, iID, isRecordKey, err1 := tablecodec.DecodeKeyHead(row.Key)
c.Assert(err1, IsNil)
c.Assert(tID, Equals, tableID)
if isRecordKey {
c.Assert(bytes.Compare(row.Key, expectRecordKey), Equals, 0)
} else {
c.Assert(iID, Equals, indexID)
c.Assert(bytes.Compare(row.Key, expectIdxKey), Equals, 0)
}
}
// unique index key
schemaSQL = `create table t1(
id int auto_increment,
a char(10),
primary key(id),
unique a_idx(a))
`
encoder.ExecDDLSQL(schemaSQL)
tableID = int64(2)
sql = "insert into t1 values(1, 'a')"
kvPairs, affectedRows, err = encoder.Encode(sql, tableID)
c.Assert(err, IsNil)
c.Assert(len(kvPairs), Equals, 2)
c.Assert(affectedRows, Equals, uint64(1))
tablePrefix = tablecodec.GenTableRecordPrefix(tableID)
handle = int64(1)
expectRecordKey = tablecodec.EncodeRecordKey(tablePrefix, handle)
indexPrefix = tablecodec.EncodeTableIndexPrefix(tableID, indexID)
expectIdxKey = []byte{}
expectIdxKey = append(expectIdxKey, []byte(indexPrefix)...)
expectIdxKey, err = codec.EncodeKey(sc, expectIdxKey, types.NewDatum([]byte("a")))
c.Assert(err, IsNil)
for _, row := range kvPairs {
tID, iID, isRecordKey, err1 := tablecodec.DecodeKeyHead(row.Key)
c.Assert(err1, IsNil)
c.Assert(tID, Equals, tableID)
if isRecordKey {
c.Assert(bytes.Compare(row.Key, expectRecordKey), Equals, 0)
} else {
c.Assert(iID, Equals, indexID)
c.Assert(bytes.Compare(row.Key, expectIdxKey), Equals, 0)
}
}
}
var (
mMetaPrefix = []byte("m")
mDBPrefix = "DB"
mTableIDPrefix = "TID"
)
func dbKey(dbID int64) []byte {
return []byte(fmt.Sprintf("%s:%d", mDBPrefix, dbID))
}
func autoTableIDKey(tableID int64) []byte {
return []byte(fmt.Sprintf("%s:%d", mTableIDPrefix, tableID))
}
func encodeHashDataKey(key []byte, field []byte) kv.Key {
ek := make([]byte, 0, len(mMetaPrefix)+len(key)+len(field)+30)
ek = append(ek, mMetaPrefix...)
ek = codec.EncodeBytes(ek, key)
ek = codec.EncodeUint(ek, uint64(structure.HashData))
return codec.EncodeBytes(ek, field)
}
func hashFieldIntegerVal(val int64) []byte {
return []byte(strconv.FormatInt(val, 10))
}
func (s *testKvEncoderSuite) TestEncodeMetaAutoID(c *C) {
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
dbID := int64(1)
tableID := int64(10)
autoID := int64(10000000111)
kvPair, err := encoder.EncodeMetaAutoID(dbID, tableID, autoID)
c.Assert(err, IsNil)
expectKey := encodeHashDataKey(dbKey(dbID), autoTableIDKey(tableID))
expectVal := hashFieldIntegerVal(autoID)
c.Assert(bytes.Compare(kvPair.Key, expectKey), Equals, 0)
c.Assert(bytes.Compare(kvPair.Val, expectVal), Equals, 0)
dbID = 10
tableID = 1
autoID = -1
kvPair, err = encoder.EncodeMetaAutoID(dbID, tableID, autoID)
c.Assert(err, IsNil)
expectKey = encodeHashDataKey(dbKey(dbID), autoTableIDKey(tableID))
expectVal = hashFieldIntegerVal(autoID)
c.Assert(bytes.Compare(kvPair.Key, expectKey), Equals, 0)
c.Assert(bytes.Compare(kvPair.Val, expectVal), Equals, 0)
}
func (s *testKvEncoderSuite) TestGetSetSystemVariable(c *C) {
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
err = encoder.SetSystemVariable("sql_mode", "")
c.Assert(err, IsNil)
val, ok := encoder.GetSystemVariable("sql_mode")
c.Assert(ok, IsTrue)
c.Assert(val, Equals, "")
sqlMode := "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
err = encoder.SetSystemVariable("sql_mode", sqlMode)
c.Assert(err, IsNil)
val, ok = encoder.GetSystemVariable("sql_mode")
c.Assert(ok, IsTrue)
c.Assert(val, Equals, sqlMode)
val, ok = encoder.GetSystemVariable("SQL_MODE")
c.Assert(ok, IsTrue)
c.Assert(val, Equals, sqlMode)
}
func (s *testKvEncoderSuite) TestDisableStrictSQLMode(c *C) {
sql := "create table `ORDER-LINE` (" +
" ol_w_id integer not null," +
" ol_d_id integer not null," +
" ol_o_id integer not null," +
" ol_number integer not null," +
" ol_i_id integer not null," +
" ol_delivery_d timestamp DEFAULT CURRENT_TIMESTAMP," +
" ol_amount decimal(6,2)," +
" ol_supply_w_id integer," +
" ol_quantity decimal(2,0)," +
" ol_dist_info char(24)," +
" primary key (ol_w_id, ol_d_id, ol_o_id, ol_number)" +
");"
encoder, err := New("test", nil)
c.Assert(err, IsNil)
defer encoder.Close()
err = encoder.ExecDDLSQL(sql)
c.Assert(err, IsNil)
tableID := int64(1)
sql = "insert into `ORDER-LINE` values(2, 1, 1, 1, 1, 'NULL', 1, 1, 1, '1');"
_, _, err = encoder.Encode(sql, tableID)
c.Assert(err, NotNil)
err = encoder.SetSystemVariable("sql_mode", "")
c.Assert(err, IsNil)
sql = "insert into `ORDER-LINE` values(2, 1, 1, 1, 1, 'NULL', 1, 1, 1, '1');"
_, _, err = encoder.Encode(sql, tableID)
c.Assert(err, IsNil)
}
func (s *testKvEncoderSuite) TestRefCount(c *C) {
var err error
var a [10]KvEncoder
for i := 0; i < 10; i++ {
a[i], err = New("test", nil)
c.Assert(err, IsNil)
}
dom1 := domGlobal
c.Assert(refCount, Equals, int64(10))
a[0].Close()
a[1].Close()
dom2 := domGlobal
c.Assert(refCount, Equals, int64(8))
c.Assert(dom1, Equals, dom2)
for i := 2; i < 9; i++ {
a[i].Close()
}
dom3 := domGlobal
c.Assert(refCount, Equals, int64(1))
c.Assert(dom3, Equals, dom2)
a[9].Close()
c.Assert(refCount, Equals, int64(0))
tmp, err := New("test", nil)
c.Assert(err, IsNil)
dom4 := domGlobal
c.Assert(dom4 == dom3, IsFalse)
c.Assert(refCount, Equals, int64(1))
tmp.Close()
c.Assert(refCount, Equals, int64(0))
}
// TestExoticDatabaseName checks if https://github.com/pingcap/tidb/issues/9532
// is fixed.
func (s *testKvEncoderSuite) TestExoticDatabaseName(c *C) {
encoder1, err := New("pay-service_micro_db", nil)
c.Assert(err, IsNil)
encoder1.Close()
encoder2, err := New("㎩¥`𝕊ℯ®Ⅵ₠—🎤肉 ㏈", nil)
c.Assert(err, IsNil)
encoder2.Close()
}