Skip to content

Commit

Permalink
Merge branch 'release-5.1' into release-5.1-03847a8ded0c
Browse files Browse the repository at this point in the history
  • Loading branch information
ClSlaid authored Jul 22, 2021
2 parents 48613c0 + 68070cb commit c9d18d1
Show file tree
Hide file tree
Showing 110 changed files with 3,110 additions and 462 deletions.
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ var defaultConf = Config{
StmtSummary: StmtSummary{
Enable: true,
EnableInternalQuery: false,
MaxStmtCount: 200,
MaxStmtCount: 3000,
MaxSQLLength: 4096,
RefreshInterval: 1800,
HistorySize: 24,
Expand Down
2 changes: 1 addition & 1 deletion config/config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ enable = true
enable-internal-query = false

# max number of statements kept in memory.
max-stmt-count = 200
max-stmt-count = 3000

# max length of displayed normalized sql and sample sql.
max-sql-length = 4096
Expand Down
54 changes: 52 additions & 2 deletions ddl/column_type_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,7 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol
tk1 := testkit.NewTestKit(c, s.store)
tk1.MustExec("use test")

tk.MustExec(fmt.Sprintf("set time_zone = 'UTC'"))
tk.MustExec("set time_zone = 'UTC'")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int not null, unique key(a))")
tk.MustExec("insert into t values(1, 1)")
Expand Down Expand Up @@ -1763,7 +1763,7 @@ func (s *testColumnTypeChangeSuite) TestChangingColOriginDefaultValueAfterAddCol
tk1 := testkit.NewTestKit(c, s.store)
tk1.MustExec("use test")

tk.MustExec(fmt.Sprintf("set time_zone = 'UTC'"))
tk.MustExec("set time_zone = 'UTC'")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a VARCHAR(31) NULL DEFAULT 'wwrzfwzb01j6ddj', b DECIMAL(12,0) NULL DEFAULT '-729850476163')")
tk.MustExec("ALTER TABLE t ADD COLUMN x CHAR(218) NULL DEFAULT 'lkittuae'")
Expand Down Expand Up @@ -2111,6 +2111,7 @@ func (s *testColumnTypeChangeSuite) TestCastToTimeStampDecodeError(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test;")

tk.MustExec("drop table if exists t")
tk.MustExec("CREATE TABLE `t` (" +
" `a` datetime DEFAULT '1764-06-11 02:46:14'" +
") ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin COMMENT='7b84832e-f857-4116-8872-82fc9dcc4ab3'")
Expand All @@ -2128,3 +2129,52 @@ func (s *testColumnTypeChangeSuite) TestCastToTimeStampDecodeError(c *C) {
// Normal cast datetime to timestamp can succeed.
tk.MustQuery("select timestamp(cast('1000-11-11 12-3-1' as date));").Check(testkit.Rows("1000-11-11 00:00:00"))
}

// Fix issue: https://github.com/pingcap/tidb/issues/26292
// Cast date to timestamp has two kind behavior: cast("3977-02-22" as date)
// For select statement, it truncate the string and return no errors. (which is 3977-02-22 00:00:00 here)
// For ddl reorging or changing column in ctc, it need report some errors.
func (s *testColumnTypeChangeSuite) TestCastDateToTimestampInReorgAttribute(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test;")

tk.MustExec("drop table if exists t")
tk.MustExec("CREATE TABLE `t` (`a` DATE NULL DEFAULT '8497-01-06')")
tk.MustExec("insert into t values(now())")

originalHook := s.dom.DDL().GetHook()
defer s.dom.DDL().(ddl.DDLForTest).SetHook(originalHook)

// use new session to check meta in callback function.
internalTK := testkit.NewTestKit(c, s.store)
internalTK.MustExec("use test")

tbl := testGetTableByName(c, tk.Se, "test", "t")
c.Assert(tbl, NotNil)
c.Assert(len(tbl.Cols()), Equals, 1)

hook := &ddl.TestDDLCallback{}
var (
checkErr1 error
checkErr2 error
)
hook.OnJobRunBeforeExported = func(job *model.Job) {
if checkErr1 != nil || checkErr2 != nil {
return
}
if tbl.Meta().ID != job.TableID {
return
}
switch job.SchemaState {
case model.StateWriteOnly:
_, checkErr1 = internalTK.Exec("insert into `t` set `a` = '3977-02-22'") // this(string) will be cast to a as date, then cast a(date) as timestamp to changing column.
_, checkErr2 = internalTK.Exec("update t set `a` = '3977-02-22'")
}
}
s.dom.DDL().(ddl.DDLForTest).SetHook(hook)

tk.MustExec("alter table t modify column a TIMESTAMP NULL DEFAULT '2021-04-28 03:35:11' FIRST")
c.Assert(checkErr1.Error(), Equals, "[types:1292]Incorrect datetime value: '3977-02-22 00:00:00'")
c.Assert(checkErr2.Error(), Equals, "[types:1292]Incorrect datetime value: '3977-02-22 00:00:00'")
tk.MustExec("drop table if exists t")
}
33 changes: 33 additions & 0 deletions ddl/db_partition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3419,3 +3419,36 @@ func (s *testSerialDBSuite1) TestAddTableWithPartition(c *C) {
) ON COMMIT DELETE ROWS;`, errno.ErrPartitionNoTemporary)
tk.MustExec("drop table if exists partition_list_table;")
}

func (s *testSerialDBSuite1) TestTruncatePartitionMultipleTimes(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists test.t;")
tk.MustExec(`create table test.t (a int primary key) partition by range (a) (
partition p0 values less than (10),
partition p1 values less than (maxvalue));`)
dom := domain.GetDomain(tk.Se)
originHook := dom.DDL().GetHook()
defer dom.DDL().SetHook(originHook)
hook := &ddl.TestDDLCallback{}
dom.DDL().SetHook(hook)
injected := false
hook.OnJobRunBeforeExported = func(job *model.Job) {
if job.Type == model.ActionTruncateTablePartition && job.SnapshotVer == 0 && !injected {
injected = true
time.Sleep(30 * time.Millisecond)
}
}
var errCount int32
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.Type == model.ActionTruncateTablePartition && job.Error != nil {
atomic.AddInt32(&errCount, 1)
}
}
done1 := make(chan error, 1)
go backgroundExec(s.store, "alter table test.t truncate partition p0;", done1)
done2 := make(chan error, 1)
go backgroundExec(s.store, "alter table test.t truncate partition p0;", done2)
<-done1
<-done2
c.Assert(errCount, LessEqual, int32(1))
}
69 changes: 69 additions & 0 deletions ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,75 @@ func (s *testDBSuite2) TestAddUniqueIndexRollback(c *C) {
testAddIndexRollback(c, s.store, s.lease, idxName, addIdxSQL, errMsg, hasNullValsInKey)
}

func (s *testSerialDBSuite) TestWriteReorgForColumnTypeChangeOnAmendTxn(c *C) {
tk2 := testkit.NewTestKit(c, s.store)
tk2.MustExec("use test_db")
tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = ON;")
defer func() {
tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = OFF;")
}()

d := s.dom.DDL()
originalHook := d.GetHook()
defer d.(ddl.DDLForTest).SetHook(originalHook)
testInsertOnModifyColumn := func(sql string, startColState, commitColState model.SchemaState, retStrs []string, retErr error) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))")
tk.MustExec("insert into t1 values (20, 20, 20);")

var checkErr error
tk1 := testkit.NewTestKit(c, s.store)
hook := &ddl.TestDDLCallback{Do: s.dom}
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.Type != model.ActionModifyColumn || checkErr != nil ||
(job.SchemaState != startColState && job.SchemaState != commitColState) {
return
}

if job.SchemaState == startColState {
tk1.MustExec("use test_db")
tk1.MustExec("begin pessimistic;")
tk1.MustExec("insert into t1 values(101, 102, 103)")
return
}
if times == 0 {
_, checkErr = tk1.Exec("commit;")
}
times++
}
d.(ddl.DDLForTest).SetHook(hook)

tk.MustExec(sql)
if retErr == nil {
c.Assert(checkErr, IsNil)
} else {
c.Assert(strings.Contains(checkErr.Error(), retErr.Error()), IsTrue)
}
tk.MustQuery("select * from t1;").Check(testkit.Rows(retStrs...))

tk.MustExec("admin check table t1")
}

// Testing it needs reorg data.
ddlStatement := "alter table t1 change column c2 cc smallint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)

// Testing it needs not reorg data. This case only have two state: none, public.
ddlStatement = "alter table t1 change column c2 cc bigint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20", "101 102 103"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, nil)
}

func (s *testSerialDBSuite) TestAddExpressionIndexRollback(c *C) {
config.UpdateGlobal(func(conf *config.Config) {
conf.Experimental.AllowsExpressionIndex = true
Expand Down
3 changes: 2 additions & 1 deletion ddl/partition.go
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,8 @@ func onTruncateTablePartition(d *ddlCtx, t *meta.Meta, job *model.Job) (int64, e
}
}
if len(newPartitions) == 0 {
return ver, table.ErrUnknownPartition.GenWithStackByArgs("drop?", tblInfo.Name.O)
job.State = model.JobStateCancelled
return ver, table.ErrUnknownPartition.GenWithStackByArgs(fmt.Sprintf("pid:%v", oldIDs), tblInfo.Name.O)
}

// Clear the tiflash replica available status.
Expand Down
2 changes: 1 addition & 1 deletion distsql/request_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (builder *RequestBuilder) Build() (*kv.Request, error) {
assertScope := val.(string)
if len(assertScope) > 0 {
if builder.IsStaleness && assertScope != builder.TxnScope {
panic("batch point get staleness option fail")
panic("request builder get staleness option fail")
}
}
})
Expand Down
2 changes: 2 additions & 0 deletions executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,8 @@ func (a *ExecStmt) FinishExecuteStmt(txnTS uint64, err error, hasMoreResults boo
}
// Reset DurationParse due to the next statement may not need to be parsed (not a text protocol query).
sessVars.DurationParse = 0
// Clean the stale read flag when statement execution finish
sessVars.StmtCtx.IsStaleness = false
}

// CloseRecordSet will finish the execution of current statement and do some record work
Expand Down
16 changes: 10 additions & 6 deletions executor/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import (
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/ranger"
"github.com/pingcap/tidb/util/sqlexec"
Expand Down Expand Up @@ -905,11 +906,6 @@ func (e *AnalyzeColumnsExec) buildSamplingStats(
}

for _, sample := range rootRowCollector.Samples {
for i := range sample.Columns {
if sample.Columns[i].Kind() == types.KindBytes {
sample.Columns[i].SetBytes(sample.Columns[i].GetBytes())
}
}
// Calculate handle from the row data for each row. It will be used to sort the samples.
sample.Handle, err = e.handleCols.BuildHandleByDatums(sample.Columns)
if err != nil {
Expand Down Expand Up @@ -1268,8 +1264,16 @@ workLoop:
if row.Columns[task.slicePos].IsNull() {
continue
}
val := row.Columns[task.slicePos]
ft := e.colsInfo[task.slicePos].FieldType
// When it's new collation data, we need to use its collate key instead of original value because only
// the collate key can ensure the correct ordering.
// This is also corresponding to similar operation in (*statistics.Column).GetColumnRowCount().
if ft.EvalType() == types.ETString {
val.SetBytes(collate.GetCollator(ft.Collate).Key(val.GetString()))
}
sampleItems = append(sampleItems, &statistics.SampleItem{
Value: row.Columns[task.slicePos],
Value: val,
Ordinal: j,
})
}
Expand Down
26 changes: 26 additions & 0 deletions executor/analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,32 @@ func (s *testSerialSuite2) TestIssue20874(c *C) {
"test t idxb 1 0 1 1 \x00A \x00A 0",
"test t idxb 1 1 3 2 \x00C \x00C 0",
))
tk.MustQuery("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, correlation from mysql.stats_histograms").Sort().Check(testkit.Rows(
"0 1 3 0 9 1 1",
"0 2 2 0 9 1 -0.5",
"1 1 3 0 0 1 0",
"1 2 2 0 0 1 0",
))
tk.MustExec("set @@tidb_analyze_version=2")
tk.MustExec("analyze table t")
tk.MustQuery("show stats_topn where db_name = 'test' and table_name = 't'").Sort().Check(testkit.Rows(
"test t a 0 \x02\xd2 1",
"test t a 0 \x0e\x0f 1",
"test t a 0 \x0e3 1",
"test t b 0 \x00A 1",
"test t b 0 \x00C 2",
"test t idxa 1 \x02\xd2 1",
"test t idxa 1 \x0e\x0f 1",
"test t idxa 1 \x0e3 1",
"test t idxb 1 \x00A 1",
"test t idxb 1 \x00C 2",
))
tk.MustQuery("select is_index, hist_id, distinct_count, null_count, tot_col_size, stats_ver, correlation from mysql.stats_histograms").Sort().Check(testkit.Rows(
"0 1 3 0 6 2 1",
"0 2 2 0 6 2 -0.5",
"1 1 3 0 6 2 0",
"1 2 2 0 6 2 0",
))
}

func (s *testSuite1) TestAnalyzeClusteredIndexPrimary(c *C) {
Expand Down
35 changes: 35 additions & 0 deletions executor/batch_point_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,23 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
if err != nil {
return err
}
// Change the unique index LOCK into PUT record.
if len(indexKeys) > 0 {
if !e.txn.Valid() {
return kv.ErrInvalidTxn
}
membuf := e.txn.GetMemBuffer()
for _, idxKey := range indexKeys {
handleVal := handleVals[string(idxKey)]
if len(handleVal) == 0 {
continue
}
err = membuf.Set(idxKey, handleVal)
if err != nil {
return err
}
}
}
}
// Fetch all values.
values, err = batchGetter.BatchGet(ctx, keys)
Expand All @@ -420,6 +437,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
if e.lock && rc {
existKeys = make([]kv.Key, 0, 2*len(values))
}
changeLockToPutIdxKeys := make([]kv.Key, 0, len(indexKeys))
e.values = make([][]byte, 0, len(values))
for i, key := range keys {
val := values[string(key)]
Expand All @@ -439,6 +457,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
// lock primary key for clustered index table is redundant
if len(indexKeys) != 0 {
existKeys = append(existKeys, indexKeys[i])
changeLockToPutIdxKeys = append(changeLockToPutIdxKeys, indexKeys[i])
}
}
}
Expand All @@ -448,6 +467,22 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
if err != nil {
return err
}
if len(changeLockToPutIdxKeys) > 0 {
if !e.txn.Valid() {
return kv.ErrInvalidTxn
}
for _, idxKey := range changeLockToPutIdxKeys {
membuf := e.txn.GetMemBuffer()
handleVal := handleVals[string(idxKey)]
if len(handleVal) == 0 {
return kv.ErrNotExist
}
err = membuf.Set(idxKey, handleVal)
if err != nil {
return err
}
}
}
}
e.handles = handles
return nil
Expand Down
Loading

0 comments on commit c9d18d1

Please sign in to comment.