Skip to content

Commit 2fb4d57

Browse files
authored
planner: fix the issue that bindings with query-level hint can not take effect for replace statements (#54048) (#54948)
close #53834
1 parent a5befaa commit 2fb4d57

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

pkg/bindinfo/session_handle_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package bindinfo_test
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"strconv"
2021
"testing"
2122
"time"
@@ -381,6 +382,25 @@ func TestDropSingleBindings(t *testing.T) {
381382
tk.MustExec("drop table t")
382383
}
383384

385+
func TestIssue53834(t *testing.T) {
386+
store := testkit.CreateMockStore(t)
387+
tk := testkit.NewTestKit(t, store)
388+
tk.MustExec(`use test`)
389+
tk.MustExec(`create table t (a varchar(1024))`)
390+
tk.MustExec(`insert into t values (space(1024))`)
391+
for i := 0; i < 12; i++ {
392+
tk.MustExec(`insert into t select * from t`)
393+
}
394+
oomAction := tk.MustQuery(`select @@tidb_mem_oom_action`).Rows()[0][0].(string)
395+
defer func() {
396+
tk.MustExec(fmt.Sprintf(`set global tidb_mem_oom_action='%v'`, oomAction))
397+
}()
398+
tk.MustExec(`set global tidb_mem_oom_action='cancel'`)
399+
tk.MustExec(`create binding using replace into t select /*+ memory_quota(1 mb) */ * from t`)
400+
err := tk.ExecToErr(`replace into t select * from t`)
401+
require.ErrorContains(t, err, "cancelled due to exceeding the allowed memory limit")
402+
}
403+
384404
func TestPreparedStmt(t *testing.T) {
385405
store := testkit.CreateMockStore(t)
386406
tk := testkit.NewTestKit(t, store)

pkg/planner/optimize.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in
281281
core.DebugTraceTryBinding(pctx, binding.Hint)
282282
}
283283
hint.BindHint(stmtNode, binding.Hint)
284-
curStmtHints, _, curWarns := hint.ParseStmtHints(binding.Hint.GetFirstTableHints(), setVarHintChecker, byte(kv.ReplicaReadFollower))
284+
curStmtHints, _, curWarns := hint.ParseStmtHints(binding.Hint.GetStmtHints(), setVarHintChecker, byte(kv.ReplicaReadFollower))
285285
sessVars.StmtCtx.StmtHints = curStmtHints
286286
// update session var by hint /set_var/
287287
for name, val := range sessVars.StmtCtx.StmtHints.SetVars {

pkg/util/hint/hint.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,16 @@ func ParseStmtHints(hints []*ast.TableOptimizerHint,
447447
return
448448
}
449449

450+
// isStmtHint checks whether this hint is a statement-level hint.
451+
func isStmtHint(h *ast.TableOptimizerHint) bool {
452+
switch h.HintName.L {
453+
case "max_execution_time", "memory_quota", "resource_group":
454+
return true
455+
default:
456+
return false
457+
}
458+
}
459+
450460
// IndexJoinHints stores hint information about index nested loop join.
451461
type IndexJoinHints struct {
452462
INLJTables []HintedTable

pkg/util/hint/hint_processor.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,20 @@ type HintsSet struct {
3939
indexHints [][]*ast.IndexHint // Slice offset is the traversal order of `TableName` in the ast.
4040
}
4141

42-
// GetFirstTableHints gets the first table hints.
43-
func (hs *HintsSet) GetFirstTableHints() []*ast.TableOptimizerHint {
42+
// GetStmtHints gets all statement-level hints.
43+
func (hs *HintsSet) GetStmtHints() []*ast.TableOptimizerHint {
44+
var result []*ast.TableOptimizerHint
4445
if len(hs.tableHints) > 0 {
45-
return hs.tableHints[0]
46+
result = append(result, hs.tableHints[0]...) // keep the same behavior with prior implementation
4647
}
47-
return nil
48+
for _, tHints := range hs.tableHints[1:] {
49+
for _, h := range tHints {
50+
if isStmtHint(h) {
51+
result = append(result, h)
52+
}
53+
}
54+
}
55+
return result
4856
}
4957

5058
// ContainTableHint checks whether the table hint set contains a hint.

0 commit comments

Comments
 (0)