diff --git a/statistics/handle/dump.go b/statistics/handle/dump.go index 33ebfdd92fb94..56492886d7953 100644 --- a/statistics/handle/dump.go +++ b/statistics/handle/dump.go @@ -97,7 +97,7 @@ func (h *Handle) DumpStatsToJSONBySnapshot(dbName string, tableInfo *model.Table } func (h *Handle) tableStatsToJSON(dbName string, tableInfo *model.TableInfo, physicalID int64, snapshot uint64) (*JSONTable, error) { - tbl, err := h.tableStatsFromStorage(tableInfo, physicalID, true, snapshot) + tbl, err := h.TableStatsFromStorage(tableInfo, physicalID, true, snapshot) if err != nil || tbl == nil { return nil, err } diff --git a/statistics/handle/handle.go b/statistics/handle/handle.go index 9dce7a5c45a7c..aaaf2475e800b 100644 --- a/statistics/handle/handle.go +++ b/statistics/handle/handle.go @@ -217,7 +217,7 @@ func (h *Handle) Update(is infoschema.InfoSchema) error { if oldTbl, ok := oldCache.tables[physicalID]; ok && oldTbl.Version >= version && tableInfo.UpdateTS == oldTbl.TblInfoUpdateTS { continue } - tbl, err := h.tableStatsFromStorage(tableInfo, physicalID, false, 0) + tbl, err := h.TableStatsFromStorage(tableInfo, physicalID, false, 0) // Error is not nil may mean that there are some ddl changes on this table, we will not update it. if err != nil { logutil.BgLogger().Error("[stats] error occurred when read table stats", zap.String("table", tableInfo.Name.O), zap.Error(err)) @@ -531,8 +531,8 @@ func (h *Handle) columnStatsFromStorage(reader *statsReader, row chunk.Row, tabl return nil } -// tableStatsFromStorage loads table stats info from storage. -func (h *Handle) tableStatsFromStorage(tableInfo *model.TableInfo, physicalID int64, loadAll bool, snapshot uint64) (_ *statistics.Table, err error) { +// TableStatsFromStorage loads table stats info from storage. +func (h *Handle) TableStatsFromStorage(tableInfo *model.TableInfo, physicalID int64, loadAll bool, snapshot uint64) (_ *statistics.Table, err error) { reader, err := h.getStatsReader(snapshot) if err != nil { return nil, err @@ -705,6 +705,12 @@ func (h *Handle) histogramFromStorage(reader *statsReader, tableID int64, colID } else { sc := &stmtctx.StatementContext{TimeZone: time.UTC} d := rows[i].GetDatum(2, &fields[2].Column.FieldType) + // When there's new collation data, the length of bounds of histogram(the collate key) might be + // longer than the FieldType.Flen of this column. + // We change it to TypeBlob to bypass the length check here. + if tp.EvalType() == types.ETString && tp.Tp != mysql.TypeEnum && tp.Tp != mysql.TypeSet { + tp = types.NewFieldType(mysql.TypeBlob) + } lowerBound, err = d.ConvertTo(sc, tp) if err != nil { return nil, errors.Trace(err) diff --git a/statistics/handle/handle_test.go b/statistics/handle/handle_test.go index c8f486efda38f..40611ac9d150e 100644 --- a/statistics/handle/handle_test.go +++ b/statistics/handle/handle_test.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/tikv/oracle" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/testkit" ) @@ -576,3 +577,31 @@ func (s *testStatsSuite) TestStatsCacheUpdateSkip(c *C) { statsTbl2 := h.GetTableStats(tableInfo) c.Assert(statsTbl1, Equals, statsTbl2) } + +var _ = SerialSuites(&statsSerialSuite{}) + +type statsSerialSuite struct { + store kv.Storage + do *domain.Domain +} + +func (s *testSerialStatsSuite) TestLoadHistogramWithCollate(c *C) { + defer cleanEnv(c, s.store, s.do) + testKit := testkit.NewTestKit(c, s.store) + collate.SetNewCollationEnabledForTest(true) + defer collate.SetNewCollationEnabledForTest(false) + testKit.MustExec("use test") + testKit.MustExec("drop table if exists t") + testKit.MustExec("create table t(a varchar(10) collate utf8mb4_unicode_ci);") + testKit.MustExec("insert into t values('abcdefghij');") + testKit.MustExec("insert into t values('abcdufghij');") + testKit.MustExec("analyze table t with 0 topn;") + do := s.do + h := do.StatsHandle() + is := do.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + c.Assert(err, IsNil) + tblInfo := tbl.Meta() + _, err = h.TableStatsFromStorage(tblInfo, tblInfo.ID, true, 0) + c.Assert(err, IsNil) +}