Skip to content

Commit 5c04d62

Browse files
authored
planner: fix the issue that bindings with query-level hint can not take effect for replace statements (#54048) (#54349)
close #53834
1 parent 2907089 commit 5c04d62

File tree

4 files changed

+44
-6
lines changed

4 files changed

+44
-6
lines changed

pkg/bindinfo/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ go_test(
5757
embed = [":bindinfo"],
5858
flaky = True,
5959
race = "on",
60-
shard_count = 43,
60+
shard_count = 44,
6161
deps = [
6262
"//pkg/bindinfo/internal",
6363
"//pkg/config",

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"
@@ -430,6 +431,25 @@ func TestDropSingleBindings(t *testing.T) {
430431
require.Len(t, rows, 0)
431432
}
432433

434+
func TestIssue53834(t *testing.T) {
435+
store := testkit.CreateMockStore(t)
436+
tk := testkit.NewTestKit(t, store)
437+
tk.MustExec(`use test`)
438+
tk.MustExec(`create table t (a varchar(1024))`)
439+
tk.MustExec(`insert into t values (space(1024))`)
440+
for i := 0; i < 12; i++ {
441+
tk.MustExec(`insert into t select * from t`)
442+
}
443+
oomAction := tk.MustQuery(`select @@tidb_mem_oom_action`).Rows()[0][0].(string)
444+
defer func() {
445+
tk.MustExec(fmt.Sprintf(`set global tidb_mem_oom_action='%v'`, oomAction))
446+
}()
447+
tk.MustExec(`set global tidb_mem_oom_action='cancel'`)
448+
tk.MustExec(`create binding for replace into t select * from t using replace into t select /*+ memory_quota(1 mb) */ * from t`)
449+
err := tk.ExecToErr(`replace into t select * from t`)
450+
require.ErrorContains(t, err, "cancelled due to exceeding the allowed memory limit")
451+
}
452+
433453
func TestPreparedStmt(t *testing.T) {
434454
store := testkit.CreateMockStore(t)
435455
tk := testkit.NewTestKit(t, store)

pkg/planner/optimize.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in
296296
}
297297
metrics.BindUsageCounter.WithLabelValues(scope).Inc()
298298
hint.BindHint(stmtNode, binding.Hint)
299-
curStmtHints, _, curWarns := handleStmtHints(binding.Hint.GetFirstTableHints())
299+
curStmtHints, _, curWarns := handleStmtHints(binding.Hint.GetStmtHints())
300300
sessVars.StmtCtx.StmtHints = curStmtHints
301301
// update session var by hint /set_var/
302302
for name, val := range sessVars.StmtCtx.StmtHints.SetVars {

pkg/util/hint/hint_processor.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,30 @@ type HintsSet struct {
4545
indexHints [][]*ast.IndexHint // Slice offset is the traversal order of `TableName` in the ast.
4646
}
4747

48-
// GetFirstTableHints gets the first table hints.
49-
func (hs *HintsSet) GetFirstTableHints() []*ast.TableOptimizerHint {
48+
// GetStmtHints gets all statement-level hints.
49+
func (hs *HintsSet) GetStmtHints() []*ast.TableOptimizerHint {
50+
var result []*ast.TableOptimizerHint
5051
if len(hs.tableHints) > 0 {
51-
return hs.tableHints[0]
52+
result = append(result, hs.tableHints[0]...) // keep the same behavior with prior implementation
53+
}
54+
for _, tHints := range hs.tableHints[1:] {
55+
for _, h := range tHints {
56+
if isStmtHint(h) {
57+
result = append(result, h)
58+
}
59+
}
60+
}
61+
return result
62+
}
63+
64+
// isStmtHint checks whether this hint is a statement-level hint.
65+
func isStmtHint(h *ast.TableOptimizerHint) bool {
66+
switch h.HintName.L {
67+
case "max_execution_time", "memory_quota", "resource_group":
68+
return true
69+
default:
70+
return false
5271
}
53-
return nil
5472
}
5573

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

0 commit comments

Comments
 (0)