Files
tidb/pkg/session/bootstrap_test.go

1886 lines
64 KiB
Go

// Copyright 2021 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package session
import (
"cmp"
"context"
"crypto/tls"
"fmt"
"slices"
"strings"
"testing"
"time"
"github.com/pingcap/failpoint"
"github.com/pingcap/kvproto/pkg/keyspacepb"
"github.com/pingcap/tidb/pkg/bindinfo"
"github.com/pingcap/tidb/pkg/config/kerneltype"
"github.com/pingcap/tidb/pkg/ddl"
"github.com/pingcap/tidb/pkg/domain"
"github.com/pingcap/tidb/pkg/expression/sessionexpr"
"github.com/pingcap/tidb/pkg/keyspace"
"github.com/pingcap/tidb/pkg/kv"
"github.com/pingcap/tidb/pkg/meta"
"github.com/pingcap/tidb/pkg/meta/metadef"
"github.com/pingcap/tidb/pkg/meta/model"
"github.com/pingcap/tidb/pkg/parser/ast"
"github.com/pingcap/tidb/pkg/parser/auth"
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/session/sessionapi"
"github.com/pingcap/tidb/pkg/sessionctx"
"github.com/pingcap/tidb/pkg/sessionctx/vardef"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
"github.com/pingcap/tidb/pkg/statistics"
"github.com/pingcap/tidb/pkg/store/mockstore"
"github.com/pingcap/tidb/pkg/store/mockstore/teststore"
"github.com/pingcap/tidb/pkg/table/tblsession"
"github.com/pingcap/tidb/pkg/telemetry"
"github.com/pingcap/tidb/pkg/testkit/testfailpoint"
"github.com/stretchr/testify/require"
"go.etcd.io/etcd/tests/v3/integration"
)
func TestMySQLDBTables(t *testing.T) {
require.Len(t, tablesInSystemDatabase, 52,
"remember to add the new tables to versionedBootstrapSchemas too")
testTableBasicInfoSlice(t, tablesInSystemDatabase)
reservedIDs := make([]int64, 0, len(ddlTableVersionTables)*2)
for _, v := range ddlTableVersionTables {
for _, tbl := range v.tables {
reservedIDs = append(reservedIDs, tbl.ID)
}
}
for _, tbl := range tablesInSystemDatabase {
reservedIDs = append(reservedIDs, tbl.ID)
}
for _, db := range systemDatabases {
reservedIDs = append(reservedIDs, db.ID)
}
slices.Sort(reservedIDs)
require.IsIncreasing(t, reservedIDs, "used IDs should be in increasing order")
require.Greater(t, reservedIDs[0], metadef.ReservedGlobalIDLowerBound, "reserved ID should be greater than ReservedGlobalIDLowerBound")
require.LessOrEqual(t, reservedIDs[len(reservedIDs)-1], metadef.ReservedGlobalIDUpperBound, "reserved ID should be less than or equal to ReservedGlobalIDUpperBound")
}
// This test file have many problem.
// 1. Please use testkit to create dom, session and store.
// 2. Don't use CreateStoreAndBootstrap and BootstrapSession together. It will cause data race.
// Please do not add any test here. You can add test case at the bootstrap_update_test.go. After All problem fixed,
// We will overwrite this file by update_test.go.
func TestBootstrap(t *testing.T) {
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
defer dom.Close()
se := CreateSessionAndSetID(t, store)
MustExec(t, se, "set global tidb_txn_mode=''")
MustExec(t, se, "use mysql")
r := MustExecToRecodeSet(t, se, "select * from user")
require.NotNil(t, r)
ctx := context.Background()
req := r.NewChunk(nil)
err := r.Next(ctx, req)
require.NoError(t, err)
require.NotEqual(t, 0, req.NumRows())
rows := statistics.RowToDatums(req.GetRow(0), r.Fields())
match(t, rows, `%`, "root", "", "mysql_native_password", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", nil, nil, nil, "", "N", time.Now(), nil, 0)
r.Close()
require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "anyhost"}, []byte(""), []byte(""), nil))
MustExec(t, se, "use test")
// Check privilege tables.
MustExec(t, se, "SELECT * from mysql.global_priv")
MustExec(t, se, "SELECT * from mysql.db")
MustExec(t, se, "SELECT * from mysql.tables_priv")
MustExec(t, se, "SELECT * from mysql.columns_priv")
MustExec(t, se, "SELECT * from mysql.global_grants")
// Check privilege tables.
r = MustExecToRecodeSet(t, se, "SELECT COUNT(*) from mysql.global_variables")
require.NotNil(t, r)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, globalVarsCount(), req.GetRow(0).GetInt64(0))
require.NoError(t, r.Close())
// Check a storage operations are default autocommit after the second start.
MustExec(t, se, "USE test")
MustExec(t, se, "drop table if exists t")
MustExec(t, se, "create table t (id int)")
store.SetOption(StoreBootstrappedKey, nil)
se.Close()
se, err = CreateSession4Test(store)
require.NoError(t, err)
MustExec(t, se, "USE test")
MustExec(t, se, "insert t values (?)", 3)
se, err = CreateSession4Test(store)
require.NoError(t, err)
MustExec(t, se, "USE test")
r = MustExecToRecodeSet(t, se, "select * from t")
require.NotNil(t, r)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
rows = statistics.RowToDatums(req.GetRow(0), r.Fields())
match(t, rows, 3)
MustExec(t, se, "drop table if exists t")
se.Close()
// Try to do bootstrap dml jobs on an already bootstrapped TiDB system will not cause fatal.
// For https://github.com/pingcap/tidb/issues/1096
se, err = CreateSession4Test(store)
require.NoError(t, err)
doDMLWorks(se)
r = MustExecToRecodeSet(t, se, "select * from mysql.expr_pushdown_blacklist where name = 'date_add'")
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 0, req.NumRows())
se.Close()
r = MustExecToRecodeSet(t, se, fmt.Sprintf("select * from mysql.bind_info where original_sql = '%s'", bindinfo.BuiltinPseudoSQL4BindLock))
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, req.NumRows())
se.Close()
}
func globalVarsCount() int64 {
var count int64
for _, v := range variable.GetSysVars() {
if v.HasGlobalScope() {
count++
}
}
return count
}
// testBootstrapWithError :
// When a session failed in bootstrap process (for example, the session is killed after doDDLWorks()).
// We should make sure that the following session could finish the bootstrap process.
func TestBootstrapWithError(t *testing.T) {
ctx := context.Background()
store, err := mockstore.NewMockStore(mockstore.WithStoreType(mockstore.EmbedUnistore))
require.NoError(t, err)
defer func() {
require.NoError(t, store.Close())
}()
// system tables are not created in `doDDLWorks` for next-gen.
if kerneltype.IsNextGen() {
require.NoError(t, bootstrapSchemas(store))
}
// bootstrap
{
se := &session{
store: store,
sessionVars: variable.NewSessionVars(nil),
}
se.exprctx = sessionexpr.NewExprContext(se)
se.pctx = newPlanContextImpl(se)
se.tblctx = tblsession.NewMutateContext(se)
globalVarsAccessor := variable.NewMockGlobalAccessor4Tests()
se.GetSessionVars().GlobalVarsAccessor = globalVarsAccessor
se.functionUsageMu.builtinFunctionUsage = make(telemetry.BuiltinFunctionsUsage)
se.txn.init()
se.mu.values = make(map[fmt.Stringer]any)
se.SetValue(sessionctx.Initing, true)
err := InitDDLTables(store)
require.NoError(t, err)
dom, err := domap.Get(store)
require.NoError(t, err)
require.NoError(t, dom.Start(ddl.Bootstrap))
se.dom = dom
se.infoCache = dom.InfoCache()
se.schemaValidator = dom.GetSchemaValidator()
b, err := checkBootstrapped(se)
require.False(t, b)
require.NoError(t, err)
doDDLWorks(se)
}
dom, err := domap.Get(store)
require.NoError(t, err)
dom.Close()
dom1, err := BootstrapSession(store)
require.NoError(t, err)
defer dom1.Close()
se := CreateSessionAndSetID(t, store)
MustExec(t, se, "USE mysql")
r := MustExecToRecodeSet(t, se, `select * from user`)
req := r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.NotEqual(t, 0, req.NumRows())
row := req.GetRow(0)
rows := statistics.RowToDatums(row, r.Fields())
match(t, rows, `%`, "root", "", "mysql_native_password", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", nil, nil, nil, "", "N", time.Now(), nil, 0)
require.NoError(t, r.Close())
MustExec(t, se, "USE test")
// Check privilege tables.
MustExec(t, se, "SELECT * from mysql.global_priv")
MustExec(t, se, "SELECT * from mysql.db")
MustExec(t, se, "SELECT * from mysql.tables_priv")
MustExec(t, se, "SELECT * from mysql.columns_priv")
// Check role tables.
MustExec(t, se, "SELECT * from mysql.role_edges")
MustExec(t, se, "SELECT * from mysql.default_roles")
// Check global variables.
r = MustExecToRecodeSet(t, se, "SELECT COUNT(*) from mysql.global_variables")
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
v := req.GetRow(0)
require.Equal(t, globalVarsCount(), v.GetInt64(0))
require.NoError(t, r.Close())
r = MustExecToRecodeSet(t, se, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="bootstrapped"`)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.NotEqual(t, 0, req.NumRows())
row = req.GetRow(0)
require.Equal(t, 1, row.Len())
require.Equal(t, []byte("True"), row.GetBytes(0))
require.NoError(t, r.Close())
MustExec(t, se, "SELECT * from mysql.tidb_background_subtask")
MustExec(t, se, "SELECT * from mysql.tidb_background_subtask_history")
// Check tidb_ttl_table_status table
MustExec(t, se, "SELECT * from mysql.tidb_ttl_table_status")
// Check mysql.tidb_workload_values table
MustExec(t, se, "SELECT * from mysql.tidb_workload_values")
}
func TestDDLTableCreateBackfillTable(t *testing.T) {
testfailpoint.Enable(t, "github.com/pingcap/tidb/pkg/ddl/skipCheckReservedSchemaObjInNextGen", "return(true)")
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
se := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
ver, err := m.GetDDLTableVersion()
require.NoError(t, err)
require.GreaterOrEqual(t, ver, meta.BackfillTableVersion)
// downgrade `mDDLTableVersion`
m.SetDDLTableVersion(meta.MDLTableVersion)
MustExec(t, se, "drop table mysql.tidb_background_subtask")
MustExec(t, se, "drop table mysql.tidb_background_subtask_history")
// TODO(lance6716): remove it after tidb_ddl_notifier GA
MustExec(t, se, "drop table mysql.tidb_ddl_notifier")
err = txn.Commit(context.Background())
require.NoError(t, err)
// to upgrade session for create ddl related tables
dom.Close()
dom, err = BootstrapSession(store)
require.NoError(t, err)
se = CreateSessionAndSetID(t, store)
MustExec(t, se, "select * from mysql.tidb_background_subtask")
MustExec(t, se, "select * from mysql.tidb_background_subtask_history")
dom.Close()
}
// TestUpgrade tests upgrading
func TestUpgrade(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
se := CreateSessionAndSetID(t, store)
MustExec(t, se, "USE mysql")
// bootstrap with currentBootstrapVersion
r := MustExecToRecodeSet(t, se, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="tidb_server_version"`)
req := r.NewChunk(nil)
err := r.Next(ctx, req)
row := req.GetRow(0)
require.NoError(t, err)
require.NotEqual(t, 0, req.NumRows())
require.Equal(t, 1, row.Len())
require.Equal(t, fmt.Appendf(nil, "%d", currentBootstrapVersion), row.GetBytes(0))
require.NoError(t, r.Close())
se1 := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(se1)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// Do something to downgrade the store.
// downgrade meta bootstrap version
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(1))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
MustExec(t, se1, `delete from mysql.TiDB where VARIABLE_NAME="tidb_server_version"`)
MustExec(t, se1, "update mysql.global_variables set variable_value='off' where variable_name='tidb_enable_dist_task'")
MustExec(t, se1, fmt.Sprintf(`delete from mysql.global_variables where VARIABLE_NAME="%s"`, vardef.TiDBDistSQLScanConcurrency))
MustExec(t, se1, `commit`)
store.SetOption(StoreBootstrappedKey, nil)
RevertVersionAndVariables(t, se1, 0)
// Make sure the version is downgraded.
r = MustExecToRecodeSet(t, se1, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="tidb_server_version"`)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 0, req.NumRows())
require.NoError(t, r.Close())
ver, err = GetBootstrapVersion(se1)
require.NoError(t, err)
require.Equal(t, int64(0), ver)
dom.Close()
// Create a new session then upgrade() will run automatically.
dom, err = BootstrapSession(store)
require.NoError(t, err)
se2 := CreateSessionAndSetID(t, store)
r = MustExecToRecodeSet(t, se2, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="tidb_server_version"`)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.NotEqual(t, 0, req.NumRows())
row = req.GetRow(0)
require.Equal(t, 1, row.Len())
require.Equal(t, fmt.Appendf(nil, "%d", currentBootstrapVersion), row.GetBytes(0))
require.NoError(t, r.Close())
ver, err = GetBootstrapVersion(se2)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// Verify that 'new_collation_enabled' is false.
r = MustExecToRecodeSet(t, se2, fmt.Sprintf(`SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME='%s'`, TidbNewCollationEnabled))
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, req.NumRows())
require.Equal(t, "False", req.GetRow(0).GetString(0))
require.NoError(t, r.Close())
r = MustExecToRecodeSet(t, se2, "admin show ddl jobs 1000;")
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
rowCnt := req.NumRows()
for i := range rowCnt {
jobType := req.GetRow(i).GetString(3) // get job type.
// Should not use multi-schema change in bootstrap DDL because the job arguments may be changed.
require.False(t, strings.Contains(jobType, "multi-schema"))
}
require.NoError(t, r.Close())
dom.Close()
}
func TestOldPasswordUpgrade(t *testing.T) {
pwd := "abc"
oldpwd := fmt.Sprintf("%X", auth.Sha1Hash([]byte(pwd)))
newpwd, err := oldPasswordUpgrade(oldpwd)
require.NoError(t, err)
require.Equal(t, "*0D3CED9BEC10A777AEC23CCC353A8C08A633045E", newpwd)
}
func TestBootstrapInitExpensiveQueryHandle(t *testing.T) {
store, _ := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
se, err := createSession(store)
require.NoError(t, err)
dom := domain.GetDomain(se)
require.NotNil(t, dom)
defer dom.Close()
require.NotNil(t, dom.ExpensiveQueryHandle())
}
func TestForIssue23387(t *testing.T) {
// For issue https://github.com/pingcap/tidb/issues/23387
saveCurrentBootstrapVersion := currentBootstrapVersion
currentBootstrapVersion = version57
// Bootstrap to an old version, create a user.
store, err := teststore.NewMockStoreWithoutBootstrap()
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, store.Close())
})
dom, err := BootstrapSession(store)
require.NoError(t, err)
se := CreateSessionAndSetID(t, store)
se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890"), nil)
MustExec(t, se, "create user quatest")
dom.Close()
// Upgrade to a newer version, check the user's privilege.
currentBootstrapVersion = saveCurrentBootstrapVersion
dom, err = BootstrapSession(store)
require.NoError(t, err)
defer dom.Close()
se = CreateSessionAndSetID(t, store)
se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890"), nil)
rs, err := exec(se, "show grants for quatest")
require.NoError(t, err)
rows, err := ResultSetToStringSlice(context.Background(), se, rs)
require.NoError(t, err)
require.Len(t, rows, 1)
require.Equal(t, "GRANT USAGE ON *.* TO 'quatest'@'%'", rows[0][0])
}
func TestIndexMergeInNewCluster(t *testing.T) {
store, err := mockstore.NewMockStore(mockstore.WithStoreType(mockstore.EmbedUnistore))
require.NoError(t, err)
// Indicates we are in a new cluster.
require.Equal(t, int64(notBootstrapped), getStoreBootstrapVersionWithCache(store))
dom, err := BootstrapSession(store)
require.NoError(t, err)
defer func() { require.NoError(t, store.Close()) }()
defer dom.Close()
se := CreateSessionAndSetID(t, store)
// In a new created cluster(above 5.4+), tidb_enable_index_merge is 1 by default.
MustExec(t, se, "use test;")
r := MustExecToRecodeSet(t, se, "select @@tidb_enable_index_merge;")
require.NotNil(t, r)
ctx := context.Background()
chk := r.NewChunk(nil)
err = r.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 1, row.Len())
require.Equal(t, int64(1), row.GetInt64(0))
}
func TestTiDBOptAdvancedJoinHintInNewCluster(t *testing.T) {
store, err := mockstore.NewMockStore(mockstore.WithStoreType(mockstore.EmbedUnistore))
require.NoError(t, err)
// Indicates we are in a new cluster.
require.Equal(t, int64(notBootstrapped), getStoreBootstrapVersionWithCache(store))
dom, err := BootstrapSession(store)
require.NoError(t, err)
defer func() { require.NoError(t, store.Close()) }()
defer dom.Close()
se := CreateSessionAndSetID(t, store)
// In a new created cluster(above 7.0+), tidb_opt_advanced_join_hint is true by default.
MustExec(t, se, "use test;")
r := MustExecToRecodeSet(t, se, "select @@tidb_opt_advanced_join_hint;")
require.NotNil(t, r)
ctx := context.Background()
chk := r.NewChunk(nil)
err = r.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 1, row.Len())
require.Equal(t, int64(1), row.GetInt64(0))
}
func TestTiDBCostModelInNewCluster(t *testing.T) {
store, err := mockstore.NewMockStore(mockstore.WithStoreType(mockstore.EmbedUnistore))
require.NoError(t, err)
// Indicates we are in a new cluster.
require.Equal(t, int64(notBootstrapped), getStoreBootstrapVersionWithCache(store))
dom, err := BootstrapSession(store)
require.NoError(t, err)
defer func() { require.NoError(t, store.Close()) }()
defer dom.Close()
se := CreateSessionAndSetID(t, store)
// In a new created cluster(above 6.5+), tidb_cost_model_version is 2 by default.
MustExec(t, se, "use test;")
r := MustExecToRecodeSet(t, se, "select @@tidb_cost_model_version;")
require.NotNil(t, r)
ctx := context.Background()
chk := r.NewChunk(nil)
err = r.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 1, row.Len())
require.Equal(t, "2", row.GetString(0))
}
func TestTiDBGCAwareUpgradeFrom630To650(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.3 to 6.5+.
ver63 := version93
seV63 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver63))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV63, ver63)
MustExec(t, seV63, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "1", vardef.TiDBEnableGCAwareMemoryTrack))
MustExec(t, seV63, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV63)
require.NoError(t, err)
require.Equal(t, int64(ver63), ver)
// We are now in 6.3, tidb_enable_gc_aware_memory_track is ON.
res := MustExecToRecodeSet(t, seV63, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBEnableGCAwareMemoryTrack))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "1", row.GetString(1))
// Upgrade to 6.5.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.5.
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBEnableGCAwareMemoryTrack))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "0", row.GetString(1))
}
func TestTiDBServerMemoryLimitUpgradeTo651_1(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.5.0 to 6.5.1+.
ver132 := version132
seV132 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver132))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV132, ver132)
MustExec(t, seV132, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "0", vardef.TiDBServerMemoryLimit))
MustExec(t, seV132, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV132)
require.NoError(t, err)
require.Equal(t, int64(ver132), ver)
// We are now in 6.5.0, tidb_server_memory_limit is 0.
res := MustExecToRecodeSet(t, seV132, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBServerMemoryLimit))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "0", row.GetString(1))
// Upgrade to 6.5.1+.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.5.1+.
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBServerMemoryLimit))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, vardef.DefTiDBServerMemoryLimit, row.GetString(1))
}
func TestTiDBServerMemoryLimitUpgradeTo651_2(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.5.0 to 6.5.1+.
ver132 := version132
seV132 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver132))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV132, ver132)
MustExec(t, seV132, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "70%", vardef.TiDBServerMemoryLimit))
MustExec(t, seV132, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV132)
require.NoError(t, err)
require.Equal(t, int64(ver132), ver)
// We are now in 6.5.0, tidb_server_memory_limit is "70%".
res := MustExecToRecodeSet(t, seV132, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBServerMemoryLimit))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "70%", row.GetString(1))
// Upgrade to 6.5.1+.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.5.1+.
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBServerMemoryLimit))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "70%", row.GetString(1))
}
func TestTiDBGlobalVariablesDefaultValueUpgradeFrom630To660(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.3.0 to 6.6.0.
ver630 := version93
seV630 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver630))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV630, ver630)
MustExec(t, seV630, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "OFF", vardef.TiDBEnableForeignKey))
MustExec(t, seV630, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "OFF", vardef.ForeignKeyChecks))
MustExec(t, seV630, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "OFF", vardef.TiDBEnableHistoricalStats))
MustExec(t, seV630, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "OFF", vardef.TiDBEnablePlanReplayerCapture))
MustExec(t, seV630, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV630)
require.NoError(t, err)
require.Equal(t, int64(ver630), ver)
// We are now in 6.3.0.
upgradeVars := []string{vardef.TiDBEnableForeignKey, vardef.ForeignKeyChecks, vardef.TiDBEnableHistoricalStats, vardef.TiDBEnablePlanReplayerCapture}
varsValueList := []string{"OFF", "OFF", "OFF", "OFF"}
for i := range upgradeVars {
res := MustExecToRecodeSet(t, seV630, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", upgradeVars[i]))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, varsValueList[i], row.GetString(1))
}
// Upgrade to 6.6.0.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seV660 := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seV660)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.6.0.
varsValueList = []string{"ON", "ON", "ON", "ON"}
for i := range upgradeVars {
res := MustExecToRecodeSet(t, seV660, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", upgradeVars[i]))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, varsValueList[i], row.GetString(1))
}
}
func TestTiDBStoreBatchSizeUpgradeFrom650To660(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
for i := range 2 {
func() {
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.5 to 6.6.
ver65 := version132
seV65 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver65))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV65, ver65)
MustExec(t, seV65, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "0", vardef.TiDBStoreBatchSize))
MustExec(t, seV65, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV65)
require.NoError(t, err)
require.Equal(t, int64(ver65), ver)
// We are now in 6.5, tidb_store_batch_size is 0.
res := MustExecToRecodeSet(t, seV65, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBStoreBatchSize))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "0", row.GetString(1))
res.Close()
if i == 0 {
// For the first time, We set tidb_store_batch_size to 1.
// And after upgrade to 6.6, tidb_store_batch_size should be 1.
// For the second it should be the latest default value.
MustExec(t, seV65, "set global tidb_store_batch_size = 1")
}
dom.Close()
// Upgrade to 6.6.
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.6.
res = MustExecToRecodeSet(t, seCurVer, "select @@tidb_store_batch_size")
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 1, row.Len())
if i == 0 {
require.Equal(t, "1", row.GetString(0))
} else {
require.Equal(t, "4", row.GetString(0))
}
res.Close()
}()
}
}
func TestTiDBUpgradeToVer136(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver135 := version135
seV135 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver135))
require.NoError(t, err)
RevertVersionAndVariables(t, seV135, ver135)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV135)
require.NoError(t, err)
require.Equal(t, int64(ver135), ver)
MustExec(t, seV135, "ALTER TABLE mysql.tidb_background_subtask DROP INDEX idx_task_key;")
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/ddl/reorgMetaRecordFastReorgDisabled", `return`))
t.Cleanup(func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/ddl/reorgMetaRecordFastReorgDisabled"))
})
MustExec(t, seV135, "set global tidb_ddl_enable_fast_reorg = 1")
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV135)
require.NoError(t, err)
require.True(t, ddl.LastReorgMetaFastReorgDisabled)
require.Less(t, int64(ver135), ver)
dom.Close()
}
func TestTiDBUpgradeToVer140(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver139 := version139
resetTo139 := func(s sessionapi.Session) {
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver139))
require.NoError(t, err)
RevertVersionAndVariables(t, s, ver139)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(s)
require.NoError(t, err)
require.Equal(t, int64(ver139), ver)
}
// drop column task_key and then upgrade
s := CreateSessionAndSetID(t, store)
MustExec(t, s, "alter table mysql.tidb_global_task drop column task_key")
resetTo139(s)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err := GetBootstrapVersion(s)
require.NoError(t, err)
require.Less(t, int64(ver139), ver)
dom.Close()
// upgrade with column task_key exists
s = CreateSessionAndSetID(t, store)
resetTo139(s)
dom, err = BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(s)
require.NoError(t, err)
require.Less(t, int64(ver139), ver)
dom.Close()
}
func TestTiDBNonPrepPlanCacheUpgradeFrom540To700(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// bootstrap to 5.4
ver54 := version82
seV54 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver54))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV54, ver54)
MustExec(t, seV54, fmt.Sprintf("delete from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBEnableNonPreparedPlanCache))
MustExec(t, seV54, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV54)
require.NoError(t, err)
require.Equal(t, int64(ver54), ver)
// We are now in 5.4, check TiDBCostModelVersion should not exist.
res := MustExecToRecodeSet(t, seV54, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBEnableNonPreparedPlanCache))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 0, chk.NumRows())
// Upgrade to 7.0
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 7.0
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBEnableNonPreparedPlanCache))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "OFF", row.GetString(1)) // tidb_enable_non_prepared_plan_cache = off
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBNonPreparedPlanCacheSize))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "100", row.GetString(1)) // tidb_non_prepared_plan_cache_size = 100
}
func TestTiDBStatsLoadPseudoTimeoutUpgradeFrom610To650(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 6.1 to 6.5+.
ver61 := version91
seV61 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver61))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV61, ver61)
MustExec(t, seV61, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "0", vardef.TiDBStatsLoadPseudoTimeout))
MustExec(t, seV61, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV61)
require.NoError(t, err)
require.Equal(t, int64(ver61), ver)
// We are now in 6.1, tidb_stats_load_pseudo_timeout is OFF.
res := MustExecToRecodeSet(t, seV61, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBStatsLoadPseudoTimeout))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "0", row.GetString(1))
// Upgrade to 6.5.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 6.5.
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBStatsLoadPseudoTimeout))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "1", row.GetString(1))
}
func TestTiDBTiDBOptTiDBOptimizerEnableNAAJWhenUpgradingToVer138(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
ver137 := version137
seV137 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver137))
require.NoError(t, err)
RevertVersionAndVariables(t, seV137, ver137)
MustExec(t, seV137, "update mysql.GLOBAL_VARIABLES set variable_value='OFF' where variable_name='tidb_enable_null_aware_anti_join'")
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV137)
require.NoError(t, err)
require.Equal(t, int64(ver137), ver)
res := MustExecToRecodeSet(t, seV137, "select * from mysql.GLOBAL_VARIABLES where variable_name='tidb_enable_null_aware_anti_join'")
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "OFF", row.GetString(1))
// Upgrade to version 138.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
res = MustExecToRecodeSet(t, seCurVer, "select * from mysql.GLOBAL_VARIABLES where variable_name='tidb_enable_null_aware_anti_join'")
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "ON", row.GetString(1))
}
func TestTiDBUpgradeToVer143(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver142 := version142
seV142 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver142))
require.NoError(t, err)
RevertVersionAndVariables(t, seV142, ver142)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV142)
require.NoError(t, err)
require.Equal(t, int64(ver142), ver)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV142)
require.NoError(t, err)
require.Less(t, int64(ver142), ver)
dom.Close()
}
func TestTiDBLoadBasedReplicaReadThresholdUpgradingToVer141(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, do := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// upgrade from 7.0 to 7.1.
ver70 := version139
seV70 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver70))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
RevertVersionAndVariables(t, seV70, ver70)
MustExec(t, seV70, fmt.Sprintf("update mysql.GLOBAL_VARIABLES set variable_value='%s' where variable_name='%s'", "0", vardef.TiDBLoadBasedReplicaReadThreshold))
MustExec(t, seV70, "commit")
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV70)
require.NoError(t, err)
require.Equal(t, int64(ver70), ver)
// We are now in 7.0, tidb_load_based_replica_read_threshold is 0.
res := MustExecToRecodeSet(t, seV70, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBLoadBasedReplicaReadThreshold))
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "0", row.GetString(1))
// Upgrade to 7.1.
do.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// We are now in 7.1.
res = MustExecToRecodeSet(t, seCurVer, fmt.Sprintf("select * from mysql.GLOBAL_VARIABLES where variable_name='%s'", vardef.TiDBLoadBasedReplicaReadThreshold))
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "1s", row.GetString(1))
}
func TestTiDBPlanCacheInvalidationOnFreshStatsWhenUpgradingToVer144(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, do := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// bootstrap as version143
ver143 := version143
seV143 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver143))
require.NoError(t, err)
RevertVersionAndVariables(t, seV143, ver143)
// simulate a real ver143 where `tidb_plan_cache_invalidation_on_fresh_stats` doesn't exist yet
MustExec(t, seV143, "delete from mysql.GLOBAL_VARIABLES where variable_name='tidb_plan_cache_invalidation_on_fresh_stats'")
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
// upgrade to ver144
do.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// the value in the table is set to OFF automatically
res := MustExecToRecodeSet(t, seCurVer, "select * from mysql.GLOBAL_VARIABLES where variable_name='tidb_plan_cache_invalidation_on_fresh_stats'")
chk := res.NewChunk(nil)
require.NoError(t, res.Next(ctx, chk))
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, "OFF", row.GetString(1))
// the session and global variable is also OFF
res = MustExecToRecodeSet(t, seCurVer, "select @@session.tidb_plan_cache_invalidation_on_fresh_stats, @@global.tidb_plan_cache_invalidation_on_fresh_stats")
chk = res.NewChunk(nil)
require.NoError(t, res.Next(ctx, chk))
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, int64(0), row.GetInt64(0))
require.Equal(t, int64(0), row.GetInt64(1))
}
func TestTiDBUpgradeToVer145(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver144 := version144
seV144 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver144))
require.NoError(t, err)
RevertVersionAndVariables(t, seV144, ver144)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV144)
require.NoError(t, err)
require.Equal(t, int64(ver144), ver)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV144)
require.NoError(t, err)
require.Less(t, int64(ver144), ver)
dom.Close()
}
func TestTiDBUpgradeToVer170(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver169 := version169
seV169 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver169))
require.NoError(t, err)
RevertVersionAndVariables(t, seV169, ver169)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV169)
require.NoError(t, err)
require.Equal(t, int64(ver169), ver)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV169)
require.NoError(t, err)
require.Less(t, int64(ver169), ver)
dom.Close()
}
func TestTiDBUpgradeToVer176(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver175 := version175
seV175 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver175))
require.NoError(t, err)
RevertVersionAndVariables(t, seV175, ver175)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV175)
require.NoError(t, err)
require.Equal(t, int64(ver175), ver)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV175)
require.NoError(t, err)
require.Less(t, int64(ver175), ver)
// Avoid reusing the old session when checking the new table.
// Otherwise it may access the previous domain, which has already been closed.
newSession := CreateSessionAndSetID(t, store)
MustExec(t, newSession, "SELECT * from mysql.tidb_global_task_history")
dom.Close()
}
func TestTiDBUpgradeToVer177(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
store, do := CreateStoreAndBootstrap(t)
defer func() {
require.NoError(t, store.Close())
}()
ver176 := version176
seV176 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver176))
require.NoError(t, err)
RevertVersionAndVariables(t, seV176, ver176)
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV176)
require.NoError(t, err)
require.Equal(t, int64(ver176), ver)
do.Close()
dom, err := BootstrapSession(store)
require.NoError(t, err)
ver, err = GetBootstrapVersion(seV176)
require.NoError(t, err)
require.Less(t, int64(ver176), ver)
// Avoid reusing the old session when checking the new table.
// Otherwise it may access the previous domain, which has already been closed.
newSession := CreateSessionAndSetID(t, store)
MustExec(t, newSession, "SELECT * from mysql.dist_framework_meta")
dom.Close()
}
func TestTiDBUpgradeToVer209(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// bootstrap as version198, version 199~208 is reserved for v8.1.x bugfix patch.
ver198 := version198
seV198 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver198))
require.NoError(t, err)
RevertVersionAndVariables(t, seV198, ver198)
// simulate a real ver198 where `tidb_resource_control_strict_mode` doesn't exist yet
MustExec(t, seV198, "delete from mysql.GLOBAL_VARIABLES where variable_name='tidb_resource_control_strict_mode'")
err = txn.Commit(context.Background())
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
// upgrade to ver209
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// the value in the table is set to OFF automatically
res := MustExecToRecodeSet(t, seCurVer, "select * from mysql.GLOBAL_VARIABLES where variable_name='tidb_resource_control_strict_mode'")
chk := res.NewChunk(nil)
require.NoError(t, res.Next(ctx, chk))
require.Equal(t, 1, chk.NumRows())
row := chk.GetRow(0)
require.Equal(t, "OFF", row.GetString(1))
// the global variable is also OFF
res = MustExecToRecodeSet(t, seCurVer, "select @@global.tidb_resource_control_strict_mode")
chk = res.NewChunk(nil)
require.NoError(t, res.Next(ctx, chk))
require.Equal(t, 1, chk.NumRows())
row = chk.GetRow(0)
require.Equal(t, int64(0), row.GetInt64(0))
require.Equal(t, false, vardef.EnableResourceControlStrictMode.Load())
}
func TestIssue61890(t *testing.T) {
testfailpoint.Enable(t, "github.com/pingcap/tidb/pkg/ddl/skipCheckReservedSchemaObjInNextGen", "return(true)")
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
s1 := CreateSessionAndSetID(t, store)
MustExec(t, s1, "drop table mysql.global_variables")
MustExec(t, s1, "create table mysql.global_variables(`VARIABLE_NAME` varchar(64) NOT NULL PRIMARY KEY clustered, `VARIABLE_VALUE` varchar(16383) DEFAULT NULL)")
s2 := CreateSessionAndSetID(t, store)
initGlobalVariableIfNotExists(s2, vardef.TiDBEnableINLJoinInnerMultiPattern, vardef.Off)
dom.Close()
}
func TestKeyspaceEtcdNamespace(t *testing.T) {
if kerneltype.IsClassic() {
t.Skip("keyspace is not supported in classic kernel")
}
keyspaceMeta := keyspacepb.KeyspaceMeta{}
keyspaceMeta.Id = 2
keyspaceMeta.Name = keyspace.System
makeStore(t, &keyspaceMeta, true)
}
func TestNullKeyspaceEtcdNamespace(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("next-gen kernel doesn't have the NULL keyspace concept")
}
makeStore(t, nil, false)
}
func makeStore(t *testing.T, keyspaceMeta *keyspacepb.KeyspaceMeta, isHasPrefix bool) {
integration.BeforeTestExternal(t)
var store kv.Storage
var err error
if keyspaceMeta != nil {
store, err = mockstore.NewMockStore(
mockstore.WithCurrentKeyspaceMeta(keyspaceMeta),
mockstore.WithStoreType(mockstore.EmbedUnistore),
)
} else {
store, err = mockstore.NewMockStore(mockstore.WithStoreType(mockstore.EmbedUnistore))
}
require.NoError(t, err)
defer func() {
require.NoError(t, store.Close())
}()
cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
defer cluster.Terminate(t)
// Build a mockEtcdBackend.
mockStore := &mockEtcdBackend{
Storage: store,
pdAddrs: []string{cluster.Members[0].GRPCURL()}}
etcdClient := cluster.RandClient()
ctx := context.Background()
require.NoError(t, ddl.StartOwnerManager(ctx, mockStore))
t.Cleanup(func() {
ddl.CloseOwnerManager(mockStore)
})
dom, err := domap.getWithEtcdClient(mockStore, etcdClient)
require.NoError(t, err)
defer dom.Close()
checkETCDNameSpace(t, dom, isHasPrefix)
}
func checkETCDNameSpace(t *testing.T, dom *domain.Domain, isHasPrefix bool) {
namespacePrefix := keyspace.MakeKeyspaceEtcdNamespace(dom.Store().GetCodec())
testKeyWithoutPrefix := "/testkey"
testVal := "test"
var expectTestKey string
if isHasPrefix {
expectTestKey = namespacePrefix + testKeyWithoutPrefix
} else {
expectTestKey = testKeyWithoutPrefix
}
// Put key value into etcd.
_, err := dom.GetEtcdClient().Put(context.Background(), testKeyWithoutPrefix, testVal)
require.NoError(t, err)
// Use expectTestKey to get the key from etcd.
getResp, err := dom.UnprefixedEtcdCli().Get(context.Background(), expectTestKey)
require.NoError(t, err)
require.Equal(t, len(getResp.Kvs), 1)
if isHasPrefix {
getResp, err = dom.UnprefixedEtcdCli().Get(context.Background(), testKeyWithoutPrefix)
require.NoError(t, err)
require.Equal(t, 0, len(getResp.Kvs))
}
}
type mockEtcdBackend struct {
kv.Storage
pdAddrs []string
}
func (mebd *mockEtcdBackend) EtcdAddrs() ([]string, error) {
return mebd.pdAddrs, nil
}
func (mebd *mockEtcdBackend) TLSConfig() *tls.Config { return nil }
func (mebd *mockEtcdBackend) StartGCWorker() error { return nil }
func TestTiDBUpgradeToVer240(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
ver239 := version239
seV239 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver239))
require.NoError(t, err)
RevertVersionAndVariables(t, seV239, ver239)
err = txn.Commit(ctx)
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
// Check if the required indexes already exist in mysql.analyze_jobs (they are created by default in new clusters)
res := MustExecToRecodeSet(t, seV239, "show create table mysql.analyze_jobs")
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
require.Contains(t, string(chk.GetRow(0).GetBytes(1)), "idx_schema_table_state")
require.Contains(t, string(chk.GetRow(0).GetBytes(1)), "idx_schema_table_partition_state")
// Check that the indexes still exist after upgrading to the new version and that no errors occurred during the upgrade.
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
res = MustExecToRecodeSet(t, seCurVer, "show create table mysql.analyze_jobs")
chk = res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
require.Contains(t, string(chk.GetRow(0).GetBytes(1)), "idx_schema_table_state")
require.Contains(t, string(chk.GetRow(0).GetBytes(1)), "idx_schema_table_partition_state")
}
func TestTiDBUpgradeToVer252(t *testing.T) {
// NOTE: this case needed to be passed in both classic and next-gen kernel.
// in the first release of next-gen kernel, the version is 250.
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
ver250 := version250
seV250 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver250))
require.NoError(t, err)
RevertVersionAndVariables(t, seV250, ver250)
err = txn.Commit(ctx)
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
getBindInfoSQLFn := func(se sessionapi.Session) string {
res := MustExecToRecodeSet(t, se, "show create table mysql.bind_info")
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
require.NoError(t, err)
require.Equal(t, 1, chk.NumRows())
return string(chk.GetRow(0).GetBytes(1))
}
createTblSQL := getBindInfoSQLFn(seV250)
require.Contains(t, createTblSQL, "`create_time` timestamp(6)")
require.Contains(t, createTblSQL, "`update_time` timestamp(6)")
// revert it back to timestamp(3) for testing. we must set below fields to
// simulate the real session in upgrade process.
seV250.SetValue(sessionctx.Initing, true)
seV250.GetSessionVars().SQLMode = mysql.ModeNone
res := MustExecToRecodeSet(t, seV250, "select create_time,update_time from mysql.bind_info")
chk := res.NewChunk(nil)
err = res.Next(ctx, chk)
for i := range chk.NumRows() {
getTime := chk.GetRow(i).GetTime(0)
getTime = chk.GetRow(i).GetTime(1)
_ = getTime
}
mustExecute(seV250, "alter table mysql.bind_info modify create_time timestamp(3)")
mustExecute(seV250, "alter table mysql.bind_info modify update_time timestamp(3)")
createTblSQL = getBindInfoSQLFn(seV250)
require.Contains(t, createTblSQL, "`create_time` timestamp(3)")
require.Contains(t, createTblSQL, "`update_time` timestamp(3)")
// do upgrade to latest version
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// check if the columns have been changed to timestamp(6)
createTblSQL = getBindInfoSQLFn(seCurVer)
require.Contains(t, createTblSQL, "`create_time` timestamp(6)")
require.Contains(t, createTblSQL, "`update_time` timestamp(6)")
}
func TestWriteClusterIDToMySQLTiDBWhenUpgradingTo242(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// `cluster_id` is inserted for a new TiDB cluster.
se := CreateSessionAndSetID(t, store)
r := MustExecToRecodeSet(t, se, `select VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME='cluster_id'`)
req := r.NewChunk(nil)
err := r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, req.NumRows())
require.NotEmpty(t, req.GetRow(0).GetBytes(0))
require.NoError(t, r.Close())
se.Close()
// bootstrap as version241
ver241 := version241
seV241 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver241))
require.NoError(t, err)
RevertVersionAndVariables(t, seV241, ver241)
// remove the cluster_id entry from mysql.tidb table
MustExec(t, seV241, "delete from mysql.tidb where variable_name='cluster_id'")
err = txn.Commit(ctx)
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
ver, err := GetBootstrapVersion(seV241)
require.NoError(t, err)
require.Equal(t, int64(ver241), ver)
seV241.Close()
// upgrade to current version
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err = GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
// check if the cluster_id has been set in the `mysql.tidb` table during upgrade
r = MustExecToRecodeSet(t, seCurVer, `select VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME='cluster_id'`)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, req.NumRows())
require.NotEmpty(t, req.GetRow(0).GetBytes(0))
require.NoError(t, r.Close())
seCurVer.Close()
}
func TestBindInfoUniqueIndex(t *testing.T) {
if kerneltype.IsNextGen() {
t.Skip("Skip this case because there is no upgrade in the first release of next-gen kernel")
}
ctx := context.Background()
store, dom := CreateStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
// bootstrap as version245
ver245 := version245
seV245 := CreateSessionAndSetID(t, store)
txn, err := store.Begin()
require.NoError(t, err)
m := meta.NewMutator(txn)
err = m.FinishBootstrap(int64(ver245))
require.NoError(t, err)
RevertVersionAndVariables(t, seV245, ver245)
err = txn.Commit(ctx)
require.NoError(t, err)
store.SetOption(StoreBootstrappedKey, nil)
// remove the unique index on mysql.bind_info for testing
MustExec(t, seV245, "alter table mysql.bind_info drop index digest_index")
// insert duplicated values into mysql.bind_info
for _, sqlDigest := range []string{"null", "'x'", "'y'"} {
for _, planDigest := range []string{"null", "'x'", "'y'"} {
insertStmt := fmt.Sprintf(`insert into mysql.bind_info values (
"sql", "bind_sql", "db", "disabled", NOW(), NOW(), "", "", "", %s, %s, null)`,
sqlDigest, planDigest)
MustExec(t, seV245, insertStmt)
MustExec(t, seV245, insertStmt)
}
}
// upgrade to current version
dom.Close()
domCurVer, err := BootstrapSession(store)
require.NoError(t, err)
defer domCurVer.Close()
seCurVer := CreateSessionAndSetID(t, store)
ver, err := GetBootstrapVersion(seCurVer)
require.NoError(t, err)
require.Equal(t, currentBootstrapVersion, ver)
}
func TestVersionedBootstrapSchemas(t *testing.T) {
require.True(t, slices.IsSortedFunc(versionedBootstrapSchemas, func(a, b versionedBootstrapSchema) int {
return cmp.Compare(a.ver, b.ver)
}), "versionedBootstrapSchemas should be sorted by version")
// make sure that later change won't affect existing version schemas.
require.Len(t, versionedBootstrapSchemas[0].databases[0].Tables, 52)
require.Len(t, versionedBootstrapSchemas[0].databases[1].Tables, 0)
allIDs := make([]int64, 0, len(versionedBootstrapSchemas))
var allTableCount int
for _, vbs := range versionedBootstrapSchemas {
for _, db := range vbs.databases {
require.Greater(t, db.ID, metadef.ReservedGlobalIDLowerBound)
require.LessOrEqual(t, db.ID, metadef.ReservedGlobalIDUpperBound)
allIDs = append(allIDs, db.ID)
testTableBasicInfoSlice(t, db.Tables)
allTableCount += len(db.Tables)
for _, tbl := range db.Tables {
allIDs = append(allIDs, tbl.ID)
}
}
}
require.Len(t, tablesInSystemDatabase, allTableCount,
"versionedBootstrapSchemas should have the same number of tables as tablesInSystemDatabase")
slices.Sort(allIDs)
require.IsIncreasing(t, allIDs, "versionedBootstrapSchemas should not have duplicate IDs")
}
func TestCheckSystemTableConstraint(t *testing.T) {
tests := []struct {
name string
setupFunc func(*model.TableInfo)
errMsg string
}{
{
name: "valid system table",
setupFunc: func(tblInfo *model.TableInfo) {
// No partition, no SepAutoInc
tblInfo.Partition = nil
tblInfo.Version = model.CurrLatestTableInfoVersion
tblInfo.AutoIDCache = 0
},
},
{
name: "table with partition should fail",
setupFunc: func(tblInfo *model.TableInfo) {
tblInfo.Partition = &model.PartitionInfo{
Type: ast.PartitionTypeRange,
Enable: true,
Definitions: []model.PartitionDefinition{},
}
tblInfo.Version = model.CurrLatestTableInfoVersion
tblInfo.AutoIDCache = 0
},
errMsg: "system table should not be partitioned table",
},
{
name: "table with SepAutoInc should fail - version 5 and AutoIDCache 1",
setupFunc: func(tblInfo *model.TableInfo) {
tblInfo.Partition = nil
tblInfo.Version = model.CurrLatestTableInfoVersion
tblInfo.AutoIDCache = 1
},
errMsg: "system table should not use AUTO_ID_CACHE=1",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tblInfo := &model.TableInfo{ID: 1, Name: ast.NewCIStr("test_table")}
tt.setupFunc(tblInfo)
err := checkSystemTableConstraint(tblInfo)
if len(tt.errMsg) > 0 {
require.ErrorContains(t, err, tt.errMsg)
} else {
require.NoError(t, err)
}
})
}
}