222 lines
8.8 KiB
Go
222 lines
8.8 KiB
Go
// Copyright 2023 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.
|
|
|
|
// Copyright 2013 The ql Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSES/QL-LICENSE file.
|
|
|
|
package session
|
|
|
|
import (
|
|
"flag"
|
|
"time"
|
|
|
|
"github.com/pingcap/tidb/pkg/session/sessionapi"
|
|
"github.com/pingcap/tidb/pkg/util/logutil"
|
|
atomicutil "go.uber.org/atomic"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// WithMockUpgrade is a flag identify whether tests run with mock upgrading.
|
|
var WithMockUpgrade *bool
|
|
|
|
// RegisterMockUpgradeFlag registers the mock upgrade flag.
|
|
func RegisterMockUpgradeFlag(fSet *flag.FlagSet) {
|
|
WithMockUpgrade = fSet.Bool("with-mock-upgrade", false, "whether tests run with mock upgrade")
|
|
}
|
|
|
|
var allDDLs = []string{
|
|
"create unique index c3_index on mock_sys_partition (c1)",
|
|
"alter table mock_sys_partition add primary key c3_index (c1)",
|
|
"alter table mock_sys_t add primary key idx_pc2 (c2)",
|
|
"alter table mock_sys_t drop primary key",
|
|
"alter table mock_sys_t add unique index idx_uc2 (c2)",
|
|
"alter table mock_sys_t add index idx_c2(c2)",
|
|
"alter table mock_sys_t add column c4 bigint",
|
|
"create table test_create_table(a int)",
|
|
"drop table test_create_table",
|
|
"alter table mock_sys_t drop column c3",
|
|
"alter table mock_sys_t_rebase auto_increment = 6000",
|
|
"alter table mock_sys_t_auto shard_row_id_bits = 5",
|
|
"alter table mock_sys_t modify column c11 mediumint",
|
|
"alter table mock_sys_t modify column c11 int",
|
|
"alter table mock_sys_t add column mayNullCol bigint default 1",
|
|
"alter table mock_sys_t modify column mayNullCol bigint default 1 not null",
|
|
"alter table mock_sys_t modify column c11 char(10)",
|
|
"alter table mock_sys_t add constraint fk foreign key a(c1) references mock_sys_t_ref(c1)",
|
|
"alter table mock_sys_t drop foreign key fk",
|
|
"rename table mock_sys_t_rename1 to mock_sys_t_rename11",
|
|
"rename table mock_sys_t_rename11 to mock_sys_t_rename111, mock_sys_t_rename2 to mock_sys_t_rename22",
|
|
"alter table mock_sys_t_cs convert to charset utf8mb4",
|
|
"alter table mock_sys_partition truncate partition p3",
|
|
"alter table mock_sys_t add column c41 bigint, add column c42 bigint",
|
|
"alter table mock_sys_t drop column c41, drop column c42",
|
|
"alter table mock_sys_t add index idx_v(c1)",
|
|
"alter table mock_sys_t alter index idx_v invisible",
|
|
"alter table mock_sys_partition add partition (partition p6 values less than (8192))",
|
|
"alter table mock_sys_partition drop partition p6",
|
|
// Should not use multi-schema change to add index in bootstrap DDL.
|
|
// "alter table mock_sys_t add index mul_idx1(c1), add index mul_idx2(c1)",
|
|
// "alter table mock_sys_t drop index mul_idx1, drop index mul_idx2",
|
|
// TODO: Support check the DB for ActionAlterPlacementPolicy.
|
|
// "alter database mock_sys_db_placement placement policy = 'alter_x'",
|
|
"alter table mock_sys_t add index rename_idx1(c1)",
|
|
"alter table mock_sys_t rename index rename_idx1 to rename_idx2",
|
|
}
|
|
|
|
var mockLatestVer = currentBootstrapVersion + 1
|
|
|
|
func mockUpgradeToVerLatest(s sessionapi.Session, ver int64) {
|
|
logutil.BgLogger().Info("mock upgrade to ver latest", zap.Int64("old ver", ver), zap.Int64("mock latest ver", mockLatestVer))
|
|
if ver >= mockLatestVer {
|
|
return
|
|
}
|
|
mustExecute(s, "use mysql")
|
|
mustExecute(s, `create table if not exists mock_sys_partition(
|
|
c1 int, c2 int, c3 int
|
|
)
|
|
partition by range( c1 ) (
|
|
partition p0 values less than (1024),
|
|
partition p1 values less than (2048),
|
|
partition p2 values less than (3072),
|
|
partition p3 values less than (4096),
|
|
partition p4 values less than (7096)
|
|
);`)
|
|
mustExecute(s, `create table if not exists mock_sys_t(
|
|
c1 int, c2 int, c3 int, c11 tinyint, index fk_c1(c1)
|
|
);`)
|
|
mustExecute(s, "create table mock_sys_t_rebase(c1 bigint auto_increment primary key, c2 bigint);")
|
|
mustExecute(s, "create table mock_sys_t_auto(c1 int not null auto_increment unique) shard_row_id_bits = 0")
|
|
mustExecute(s, "create table mock_sys_t_ref (c1 int key, c2 int, c3 int, c11 tinyint);")
|
|
mustExecute(s, "create table mock_sys_t_rename1(c1 bigint, c2 bigint);")
|
|
mustExecute(s, "create table mock_sys_t_rename2(c1 bigint, c2 bigint);")
|
|
mustExecute(s, "create table mock_sys_t_cs(a varchar(10)) charset utf8")
|
|
mustExecute(s, "create table mock_sys_t_partition2(c1 int, c2 int, c3 int)")
|
|
mustExecute(s, "set @@tidb_enable_exchange_partition=1")
|
|
// TODO: Support check the DB for ActionCreatePlacementPolicy.
|
|
// mustExecute(s, "create placement policy alter_x PRIMARY_REGION=\"cn-east-1\", REGIONS=\"cn-east-1\";")
|
|
for _, sql := range allDDLs {
|
|
TestHook.OnBootstrap(s)
|
|
mustExecute(s, sql)
|
|
logutil.BgLogger().Info("mock upgrade exec", zap.String("sql", sql))
|
|
time.Sleep(20 * time.Millisecond)
|
|
}
|
|
TestHook.OnBootstrapAfter(s)
|
|
}
|
|
|
|
// mockSimpleUpgradeToVerLatest mocks a simple bootstrapVersion(make the test faster).
|
|
func mockSimpleUpgradeToVerLatest(s sessionapi.Session, ver int64) {
|
|
logutil.BgLogger().Info("mock upgrade to ver latest", zap.Int64("old ver", ver), zap.Int64("mock latest ver", mockLatestVer))
|
|
if ver >= mockLatestVer {
|
|
return
|
|
}
|
|
mustExecute(s, "use mysql")
|
|
mustExecute(s, `create table if not exists mock_sys_t(
|
|
c1 int, c2 int, c3 int, c11 tinyint, index fk_c1(c1)
|
|
);`)
|
|
mustExecute(s, "alter table mock_sys_t add column mayNullCol bigint default 1")
|
|
mustExecute(s, "alter table mock_sys_t add index idx_c2(c2)")
|
|
TestHook.OnBootstrapAfter(s)
|
|
}
|
|
|
|
// TestHook is exported for testing.
|
|
var TestHook = TestCallback{}
|
|
|
|
// modifyBootstrapVersionForTest is used to test SupportUpgradeHTTPOpVer upgrade SupportUpgradeHTTPOpVer++.
|
|
func modifyBootstrapVersionForTest(ver int64) {
|
|
if WithMockUpgrade == nil || !*WithMockUpgrade {
|
|
return
|
|
}
|
|
|
|
if ver >= SupportUpgradeHTTPOpVer && currentBootstrapVersion >= SupportUpgradeHTTPOpVer {
|
|
currentBootstrapVersion = mockLatestVer
|
|
}
|
|
}
|
|
|
|
const (
|
|
defaultMockUpgradeToVerLatest = 0
|
|
// MockSimpleUpgradeToVerLatest is used to indicate the use of the simple mock bootstrapVersion, this is just a few simple DDL operations.
|
|
MockSimpleUpgradeToVerLatest = 1
|
|
)
|
|
|
|
// MockUpgradeToVerLatestKind is used to indicate the use of different mock bootstrapVersion.
|
|
var MockUpgradeToVerLatestKind = defaultMockUpgradeToVerLatest
|
|
|
|
func addMockBootstrapVersionForTest(s sessionapi.Session) []versionedUpgradeFunction {
|
|
if WithMockUpgrade == nil || !*WithMockUpgrade {
|
|
return upgradeToVerFunctions
|
|
}
|
|
|
|
TestHook.OnBootstrapBefore(s)
|
|
currentBootstrapVersion = mockLatestVer
|
|
additionalUpgradeFn := versionedUpgradeFunction{version: mockLatestVer, fn: mockUpgradeToVerLatest}
|
|
if MockUpgradeToVerLatestKind == MockSimpleUpgradeToVerLatest {
|
|
additionalUpgradeFn = versionedUpgradeFunction{version: mockLatestVer, fn: mockSimpleUpgradeToVerLatest}
|
|
}
|
|
return append(upgradeToVerFunctions, additionalUpgradeFn)
|
|
}
|
|
|
|
// Callback is used for Test.
|
|
type Callback interface {
|
|
// OnBootstrapBefore is called before doing bootstrap.
|
|
OnBootstrapBefore(s sessionapi.Session)
|
|
// OnBootstrap is called doing bootstrap.
|
|
OnBootstrap(s sessionapi.Session)
|
|
// OnBootstrapAfter is called after doing bootstrap.
|
|
OnBootstrapAfter(s sessionapi.Session)
|
|
}
|
|
|
|
// BaseCallback implements Callback interfaces.
|
|
type BaseCallback struct{}
|
|
|
|
// OnBootstrapBefore implements Callback interface.
|
|
func (*BaseCallback) OnBootstrapBefore(sessionapi.Session) {}
|
|
|
|
// OnBootstrap implements Callback interface.
|
|
func (*BaseCallback) OnBootstrap(sessionapi.Session) {}
|
|
|
|
// OnBootstrapAfter implements Callback interface.
|
|
func (*BaseCallback) OnBootstrapAfter(sessionapi.Session) {}
|
|
|
|
// TestCallback is used to customize user callback themselves.
|
|
type TestCallback struct {
|
|
*BaseCallback
|
|
|
|
Cnt *atomicutil.Int32
|
|
OnBootstrapBeforeExported func(s sessionapi.Session)
|
|
OnBootstrapExported func(s sessionapi.Session)
|
|
OnBootstrapAfterExported func(s sessionapi.Session)
|
|
}
|
|
|
|
// OnBootstrapBefore mocks the same behavior with the main bootstrap hook.
|
|
func (tc *TestCallback) OnBootstrapBefore(s sessionapi.Session) {
|
|
if tc.OnBootstrapBeforeExported != nil {
|
|
tc.OnBootstrapBeforeExported(s)
|
|
}
|
|
}
|
|
|
|
// OnBootstrap mocks the same behavior with the main bootstrap hook.
|
|
func (tc *TestCallback) OnBootstrap(s sessionapi.Session) {
|
|
if tc.OnBootstrapExported != nil {
|
|
tc.OnBootstrapExported(s)
|
|
}
|
|
}
|
|
|
|
// OnBootstrapAfter mocks the same behavior with the main bootstrap hook.
|
|
func (tc *TestCallback) OnBootstrapAfter(s sessionapi.Session) {
|
|
if tc.OnBootstrapAfterExported != nil {
|
|
tc.OnBootstrapAfterExported(s)
|
|
}
|
|
}
|