Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser: allow drop stats of multiple tables #38042

Merged
merged 4 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions executor/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -1776,14 +1776,24 @@ func (e *SimpleExec) executeAlterInstance(s *ast.AlterInstanceStmt) error {
func (e *SimpleExec) executeDropStats(s *ast.DropStatsStmt) (err error) {
h := domain.GetDomain(e.ctx).StatsHandle()
var statsIDs []int64
// TODO: GLOBAL option will be deprecated. Also remove this condition when the syntax is removed
if s.IsGlobalStats {
statsIDs = []int64{s.Table.TableInfo.ID}
statsIDs = []int64{s.Tables[0].TableInfo.ID}
} else {
if statsIDs, _, err = core.GetPhysicalIDsAndPartitionNames(s.Table.TableInfo, s.PartitionNames); err != nil {
return err
}
if len(s.PartitionNames) == 0 {
statsIDs = append(statsIDs, s.Table.TableInfo.ID)
for _, table := range s.Tables {
partitionStatIds, _, err := core.GetPhysicalIDsAndPartitionNames(table.TableInfo, nil)
if err != nil {
return err
}
statsIDs = append(statsIDs, partitionStatIds...)
statsIDs = append(statsIDs, table.TableInfo.ID)
}
} else {
// TODO: drop stats for specific partition is deprecated. Also remove this condition when the syntax is removed
if statsIDs, _, err = core.GetPhysicalIDsAndPartitionNames(s.Tables[0].TableInfo, s.PartitionNames); err != nil {
return err
}
}
}
if err := h.DeleteTableStatsFromKV(statsIDs); err != nil {
Expand Down
49 changes: 49 additions & 0 deletions executor/simpletest/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,7 @@ partition by range (a) (
checkPartitionStats("global", "p0", "p1", "global")

tk.MustExec("drop stats test_drop_gstats partition p0")
tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1681|'DROP STATS ... PARTITION ...' is deprecated and will be removed in a future release."))
checkPartitionStats("global", "p1", "global")

err := tk.ExecToErr("drop stats test_drop_gstats partition abcde")
Expand All @@ -1010,6 +1011,7 @@ partition by range (a) (
checkPartitionStats("global", "p1")

tk.MustExec("drop stats test_drop_gstats global")
tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning|1287|'DROP STATS ... GLOBAL' is deprecated and will be removed in a future release. Please use DROP STATS ... instead"))
checkPartitionStats("p1")

tk.MustExec("analyze table test_drop_gstats")
Expand Down Expand Up @@ -1056,3 +1058,50 @@ func TestDropStats(t *testing.T) {
require.True(t, statsTbl.Pseudo)
h.SetLease(0)
}

func TestDropStatsForMultipleTable(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
testKit := testkit.NewTestKit(t, store)
testKit.MustExec("use test")
testKit.MustExec("create table t1 (c1 int, c2 int)")
testKit.MustExec("create table t2 (c1 int, c2 int)")

is := dom.InfoSchema()
tbl1, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1"))
require.NoError(t, err)
tableInfo1 := tbl1.Meta()

tbl2, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t2"))
require.NoError(t, err)
tableInfo2 := tbl2.Meta()

h := dom.StatsHandle()
h.Clear()
testKit.MustExec("analyze table t1, t2")
statsTbl1 := h.GetTableStats(tableInfo1)
require.False(t, statsTbl1.Pseudo)
statsTbl2 := h.GetTableStats(tableInfo2)
require.False(t, statsTbl2.Pseudo)

testKit.MustExec("drop stats t1, t2")
require.Nil(t, h.Update(is))
statsTbl1 = h.GetTableStats(tableInfo1)
require.True(t, statsTbl1.Pseudo)
statsTbl2 = h.GetTableStats(tableInfo2)
require.True(t, statsTbl2.Pseudo)

testKit.MustExec("analyze table t1, t2")
statsTbl1 = h.GetTableStats(tableInfo1)
require.False(t, statsTbl1.Pseudo)
statsTbl2 = h.GetTableStats(tableInfo2)
require.False(t, statsTbl2.Pseudo)

h.SetLease(1)
testKit.MustExec("drop stats t1, t2")
require.Nil(t, h.Update(is))
statsTbl1 = h.GetTableStats(tableInfo1)
require.True(t, statsTbl1.Pseudo)
statsTbl2 = h.GetTableStats(tableInfo2)
require.True(t, statsTbl2.Pseudo)
h.SetLease(0)
}
6 changes: 5 additions & 1 deletion parser/ast/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ func TestMiscVisitorCover(t *testing.T) {
&ast.PrivElem{},
&ast.VariableAssignment{Value: valueExpr},
&ast.KillStmt{},
&ast.DropStatsStmt{Table: &ast.TableName{}},
&ast.DropStatsStmt{
Tables: []*ast.TableName{
{},
},
},
&ast.ShutdownStmt{},
}

Expand Down
23 changes: 16 additions & 7 deletions parser/ast/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,26 @@ func (n *AnalyzeTableStmt) Accept(v Visitor) (Node, bool) {
}

// DropStatsStmt is used to drop table statistics.
// if the PartitionNames is not empty, or IsGlobalStats is true, it will contain exactly one table
type DropStatsStmt struct {
stmtNode

Table *TableName
Tables []*TableName
PartitionNames []model.CIStr
IsGlobalStats bool
}

// Restore implements Node interface.
func (n *DropStatsStmt) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("DROP STATS ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while add table")

for index, table := range n.Tables {
if index != 0 {
ctx.WritePlain(", ")
}
if err := table.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore DropStatsStmt.Tables[%d]", index)
}
}

if n.IsGlobalStats {
Expand All @@ -228,11 +235,13 @@ func (n *DropStatsStmt) Accept(v Visitor) (Node, bool) {
return v.Leave(newNode)
}
n = newNode.(*DropStatsStmt)
node, ok := n.Table.Accept(v)
if !ok {
return n, false
for i, val := range n.Tables {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Tables[i] = node.(*TableName)
}
n.Table = node.(*TableName)
return v.Leave(n)
}

Expand Down
677 changes: 341 additions & 336 deletions parser/parser.go

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -4779,21 +4779,25 @@ DropRoleStmt:
}

DropStatsStmt:
"DROP" "STATS" TableName
"DROP" "STATS" TableNameList
{
$$ = &ast.DropStatsStmt{Table: $3.(*ast.TableName)}
$$ = &ast.DropStatsStmt{Tables: $3.([]*ast.TableName)}
}
| "DROP" "STATS" TableName "PARTITION" PartitionNameList
{
yylex.AppendError(ErrWarnDeprecatedSyntaxNoReplacement.FastGenByArgs("DROP STATS ... PARTITION ..."))
parser.lastErrorAsWarn()
$$ = &ast.DropStatsStmt{
Table: $3.(*ast.TableName),
Tables: []*ast.TableName{$3.(*ast.TableName)},
PartitionNames: $5.([]model.CIStr),
}
}
| "DROP" "STATS" TableName "GLOBAL"
{
yylex.AppendError(ErrWarnDeprecatedSyntax.FastGenByArgs("DROP STATS ... GLOBAL", "DROP STATS ..."))
parser.lastErrorAsWarn()
$$ = &ast.DropStatsStmt{
Table: $3.(*ast.TableName),
Tables: []*ast.TableName{$3.(*ast.TableName)},
IsGlobalStats: true,
}
}
Expand Down
3 changes: 2 additions & 1 deletion parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2660,9 +2660,10 @@ func TestDDL(t *testing.T) {
{"drop view if exists xxx", true, "DROP VIEW IF EXISTS `xxx`"},
{"drop view if exists xxx, yyy", true, "DROP VIEW IF EXISTS `xxx`, `yyy`"},
{"drop stats t", true, "DROP STATS `t`"},
{"drop stats t1, t2, t3", true, "DROP STATS `t1`, `t2`, `t3`"},
{"drop stats t global", true, "DROP STATS `t` GLOBAL"},
{"drop stats t partition p0", true, "DROP STATS `t` PARTITION `p0`"},
{"drop stats t partition p0, p1, p2", true, "DROP STATS `t` PARTITION `p0`,`p1`,`p2`"},
{"drop stats t global", true, "DROP STATS `t` GLOBAL"},
// for issue 974
{`CREATE TABLE address (
id bigint(20) NOT NULL AUTO_INCREMENT,
Expand Down
2 changes: 2 additions & 0 deletions parser/yy_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ var (
ErrUnknownAlterAlgorithm = terror.ClassParser.NewStd(mysql.ErrUnknownAlterAlgorithm)
// ErrWrongValue returns for wrong value
ErrWrongValue = terror.ClassParser.NewStd(mysql.ErrWrongValue)
// ErrWarnDeprecatedSyntax return when the syntax was deprecated
ErrWarnDeprecatedSyntax = terror.ClassParser.NewStd(mysql.ErrWarnDeprecatedSyntax)
// ErrWarnDeprecatedSyntaxNoReplacement return when the syntax was deprecated and there is no replacement.
ErrWarnDeprecatedSyntaxNoReplacement = terror.ClassParser.NewStd(mysql.ErrWarnDeprecatedSyntaxNoReplacement)
// ErrWarnDeprecatedIntegerDisplayWidth share the same code 1681, and it will be returned when length is specified in integer.
Expand Down