Skip to content

Commit

Permalink
planner: fix the issue that bindings with query-level hint can not ta…
Browse files Browse the repository at this point in the history
…ke effect for replace statements (#54048) (#54349)

close #53834
  • Loading branch information
ti-chi-bot authored Jul 15, 2024
1 parent 2907089 commit 5c04d62
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pkg/bindinfo/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ go_test(
embed = [":bindinfo"],
flaky = True,
race = "on",
shard_count = 43,
shard_count = 44,
deps = [
"//pkg/bindinfo/internal",
"//pkg/config",
Expand Down
20 changes: 20 additions & 0 deletions pkg/bindinfo/session_handle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package bindinfo_test

import (
"context"
"fmt"
"strconv"
"testing"
"time"
Expand Down Expand Up @@ -430,6 +431,25 @@ func TestDropSingleBindings(t *testing.T) {
require.Len(t, rows, 0)
}

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`)
}
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 for replace into t select * from t 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")
}

func TestPreparedStmt(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down
2 changes: 1 addition & 1 deletion pkg/planner/optimize.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in
}
metrics.BindUsageCounter.WithLabelValues(scope).Inc()
hint.BindHint(stmtNode, binding.Hint)
curStmtHints, _, curWarns := handleStmtHints(binding.Hint.GetFirstTableHints())
curStmtHints, _, curWarns := handleStmtHints(binding.Hint.GetStmtHints())
sessVars.StmtCtx.StmtHints = curStmtHints
// update session var by hint /set_var/
for name, val := range sessVars.StmtCtx.StmtHints.SetVars {
Expand Down
26 changes: 22 additions & 4 deletions pkg/util/hint/hint_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,30 @@ 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 result
}

// 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
}
return nil
}

// ContainTableHint checks whether the table hint set contains a hint.
Expand Down

0 comments on commit 5c04d62

Please sign in to comment.