From 2f9fa5f409daed595d8e085345cd7962e148bf03 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Mon, 17 Jun 2024 14:43:12 +0800 Subject: [PATCH 1/6] fixup --- pkg/bindinfo/session_handle_test.go | 13 +++++++++++++ pkg/util/hint/hint_processor.go | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pkg/bindinfo/session_handle_test.go b/pkg/bindinfo/session_handle_test.go index ebbe4bd6471fc..4ea95e6357f24 100644 --- a/pkg/bindinfo/session_handle_test.go +++ b/pkg/bindinfo/session_handle_test.go @@ -381,6 +381,19 @@ func TestDropSingleBindings(t *testing.T) { tk.MustExec("drop table t") } +func TestIssue53834(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`create table t (a varchar(1024))`) + tk.MustExec(`insert into t values (space(1024))`) + for i := 0; i < 12; i++ { + tk.MustExec(`insert into t select * from t`) + } + tk.MustExec(`create binding using replace /*+ memory_quota(1 mb) */ into t select * from t`) + tk.MustExec(`replace into t select * from t`) +} + func TestPreparedStmt(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/pkg/util/hint/hint_processor.go b/pkg/util/hint/hint_processor.go index 728d0b06f0f3a..68f317e205854 100644 --- a/pkg/util/hint/hint_processor.go +++ b/pkg/util/hint/hint_processor.go @@ -68,6 +68,8 @@ func setTableHints4StmtNode(node ast.Node, hints []*ast.TableOptimizerHint) { x.TableHints = hints case *ast.DeleteStmt: x.TableHints = hints + case *ast.InsertStmt: + x.TableHints = hints } } @@ -203,7 +205,7 @@ type hintProcessor struct { func (hp *hintProcessor) Enter(in ast.Node) (ast.Node, bool) { switch v := in.(type) { - case *ast.SelectStmt, *ast.UpdateStmt, *ast.DeleteStmt: + case *ast.SelectStmt, *ast.UpdateStmt, *ast.DeleteStmt, *ast.InsertStmt: if hp.bindHint2Ast { if hp.tableCounter < len(hp.tableHints) { setTableHints4StmtNode(in, hp.tableHints[hp.tableCounter]) From bd6137d0b8ab642eeffe661eca675b7cbb66acf5 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Mon, 17 Jun 2024 15:05:31 +0800 Subject: [PATCH 2/6] fixup --- pkg/bindinfo/session_handle_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/bindinfo/session_handle_test.go b/pkg/bindinfo/session_handle_test.go index 4ea95e6357f24..7be42b76e1107 100644 --- a/pkg/bindinfo/session_handle_test.go +++ b/pkg/bindinfo/session_handle_test.go @@ -16,6 +16,7 @@ package bindinfo_test import ( "context" + "fmt" "strconv" "testing" "time" @@ -390,8 +391,14 @@ func TestIssue53834(t *testing.T) { for i := 0; i < 12; i++ { tk.MustExec(`insert into t select * from t`) } + oomAction := tk.MustQuery(`select @@tidb_mem_oom_action`).Rows()[0][0].(string) + defer func() { + tk.MustExec(fmt.Sprintf(`set global tidb_mem_oom_action='%v'`, oomAction)) + }() + tk.MustExec(`set global tidb_mem_oom_action='cancel'`) tk.MustExec(`create binding using replace /*+ memory_quota(1 mb) */ into t select * from t`) - tk.MustExec(`replace into t select * from t`) + err := tk.ExecToErr(`replace into t select * from t`) + require.ErrorContains(t, err, "cancelled due to exceeding the allowed memory limit") } func TestPreparedStmt(t *testing.T) { From e6a367896241d8fda79d5617231b0699a59b6cdf Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 18 Jun 2024 11:19:49 +0800 Subject: [PATCH 3/6] fixup --- pkg/util/hint/hint_processor.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/util/hint/hint_processor.go b/pkg/util/hint/hint_processor.go index 68f317e205854..728d0b06f0f3a 100644 --- a/pkg/util/hint/hint_processor.go +++ b/pkg/util/hint/hint_processor.go @@ -68,8 +68,6 @@ func setTableHints4StmtNode(node ast.Node, hints []*ast.TableOptimizerHint) { x.TableHints = hints case *ast.DeleteStmt: x.TableHints = hints - case *ast.InsertStmt: - x.TableHints = hints } } @@ -205,7 +203,7 @@ type hintProcessor struct { func (hp *hintProcessor) Enter(in ast.Node) (ast.Node, bool) { switch v := in.(type) { - case *ast.SelectStmt, *ast.UpdateStmt, *ast.DeleteStmt, *ast.InsertStmt: + case *ast.SelectStmt, *ast.UpdateStmt, *ast.DeleteStmt: if hp.bindHint2Ast { if hp.tableCounter < len(hp.tableHints) { setTableHints4StmtNode(in, hp.tableHints[hp.tableCounter]) From a02afddfa7672bfd38b9082c2cb31c4107d2b0e8 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 18 Jun 2024 11:29:07 +0800 Subject: [PATCH 4/6] fixup --- pkg/planner/optimize.go | 2 +- pkg/util/hint/hint.go | 10 ++++++++++ pkg/util/hint/hint_processor.go | 14 +++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pkg/planner/optimize.go b/pkg/planner/optimize.go index 915fc537fcbc9..1754606474097 100644 --- a/pkg/planner/optimize.go +++ b/pkg/planner/optimize.go @@ -281,7 +281,7 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in core.DebugTraceTryBinding(pctx, binding.Hint) } hint.BindHint(stmtNode, binding.Hint) - curStmtHints, _, curWarns := hint.ParseStmtHints(binding.Hint.GetFirstTableHints(), setVarHintChecker, byte(kv.ReplicaReadFollower)) + curStmtHints, _, curWarns := hint.ParseStmtHints(binding.Hint.GetStmtHints(), setVarHintChecker, byte(kv.ReplicaReadFollower)) sessVars.StmtCtx.StmtHints = curStmtHints // update session var by hint /set_var/ for name, val := range sessVars.StmtCtx.StmtHints.SetVars { diff --git a/pkg/util/hint/hint.go b/pkg/util/hint/hint.go index e940b6f12b5c5..e1683f1f90cfe 100644 --- a/pkg/util/hint/hint.go +++ b/pkg/util/hint/hint.go @@ -447,6 +447,16 @@ func ParseStmtHints(hints []*ast.TableOptimizerHint, return } +// isStmtHint checks whether this hint is a statement-level hint. +func isStmtHint(h *ast.TableOptimizerHint) bool { + switch h.HintName.L { + case "max_execution_time", "memory_quota", "resource_group": + return true + default: + return false + } +} + // IndexJoinHints stores hint information about index nested loop join. type IndexJoinHints struct { INLJTables []HintedTable diff --git a/pkg/util/hint/hint_processor.go b/pkg/util/hint/hint_processor.go index 728d0b06f0f3a..8355b7968049e 100644 --- a/pkg/util/hint/hint_processor.go +++ b/pkg/util/hint/hint_processor.go @@ -39,10 +39,18 @@ type HintsSet struct { indexHints [][]*ast.IndexHint // Slice offset is the traversal order of `TableName` in the ast. } -// GetFirstTableHints gets the first table hints. -func (hs *HintsSet) GetFirstTableHints() []*ast.TableOptimizerHint { +// GetStmtHints gets all statement-level hints. +func (hs *HintsSet) GetStmtHints() []*ast.TableOptimizerHint { + var result []*ast.TableOptimizerHint if len(hs.tableHints) > 0 { - return hs.tableHints[0] + result = append(result, hs.tableHints[0]...) // keep the same behavior with prior implementation + } + for _, tHints := range hs.tableHints[1:] { + for _, h := range tHints { + if isStmtHint(h) { + result = append(result, h) + } + } } return nil } From a3991c43362c27f64ec7276a0b0d11f2b76aaf37 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 18 Jun 2024 11:39:23 +0800 Subject: [PATCH 5/6] fixup --- pkg/util/hint/hint_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/hint/hint_processor.go b/pkg/util/hint/hint_processor.go index 8355b7968049e..dff5712c76f62 100644 --- a/pkg/util/hint/hint_processor.go +++ b/pkg/util/hint/hint_processor.go @@ -52,7 +52,7 @@ func (hs *HintsSet) GetStmtHints() []*ast.TableOptimizerHint { } } } - return nil + return result } // ContainTableHint checks whether the table hint set contains a hint. From fe558805a3afe26c87e9017551d866101ff2dcfe Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 18 Jun 2024 11:41:30 +0800 Subject: [PATCH 6/6] fixup --- pkg/bindinfo/session_handle_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/bindinfo/session_handle_test.go b/pkg/bindinfo/session_handle_test.go index 7be42b76e1107..ae653ef17297a 100644 --- a/pkg/bindinfo/session_handle_test.go +++ b/pkg/bindinfo/session_handle_test.go @@ -396,7 +396,7 @@ func TestIssue53834(t *testing.T) { tk.MustExec(fmt.Sprintf(`set global tidb_mem_oom_action='%v'`, oomAction)) }() tk.MustExec(`set global tidb_mem_oom_action='cancel'`) - tk.MustExec(`create binding using replace /*+ memory_quota(1 mb) */ into t select * from t`) + tk.MustExec(`create binding using replace into t select /*+ memory_quota(1 mb) */ * from t`) err := tk.ExecToErr(`replace into t select * from t`) require.ErrorContains(t, err, "cancelled due to exceeding the allowed memory limit") }