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

planner: move more hint code to the hint package #50756

Merged
merged 1 commit into from
Jan 26, 2024
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
191 changes: 8 additions & 183 deletions pkg/planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3954,191 +3954,16 @@ func (b *PlanBuilder) pushHintWithoutTableWarning(hint *ast.TableOptimizerHint)

func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLevel int) {
hints = b.hintProcessor.GetCurrentStmtHints(hints, currentLevel)
var (
sortMergeTables, inljTables, inlhjTables, inlmjTables, hashJoinTables, bcTables []h.HintedTable
noIndexJoinTables, noIndexHashJoinTables, noIndexMergeJoinTables []h.HintedTable
noHashJoinTables, noMergeJoinTables []h.HintedTable
shuffleJoinTables []h.HintedTable
indexHintList, indexMergeHintList []h.HintedIndex
tiflashTables, tikvTables []h.HintedTable
aggHints h.AggHints
timeRangeHint ast.HintTimeRange
preferLimitToCop bool
cteMerge bool
leadingJoinOrder []h.HintedTable
hjBuildTables, hjProbeTables []h.HintedTable
leadingHintCnt int
)
currentDB := b.ctx.GetSessionVars().CurrentDB
warnHandler := b.ctx.GetSessionVars().StmtCtx
for _, hint := range hints {
// Set warning for the hint that requires the table name.
switch hint.HintName.L {
case h.TiDBMergeJoin, h.HintSMJ, h.TiDBIndexNestedLoopJoin, h.HintINLJ, h.HintINLHJ, h.HintINLMJ,
h.HintNoHashJoin, h.HintNoMergeJoin, h.TiDBHashJoin, h.HintHJ, h.HintUseIndex, h.HintIgnoreIndex,
h.HintForceIndex, h.HintOrderIndex, h.HintNoOrderIndex, h.HintIndexMerge, h.HintLeading:
if len(hint.Tables) == 0 {
var sb strings.Builder
ctx := format.NewRestoreCtx(0, &sb)
if err := hint.Restore(ctx); err != nil {
return
}
errMsg := fmt.Sprintf("Hint %s is inapplicable. Please specify the table names in the arguments.", sb.String())
b.ctx.GetSessionVars().StmtCtx.SetHintWarning(errMsg)
continue
}
}

switch hint.HintName.L {
case h.TiDBMergeJoin, h.HintSMJ:
sortMergeTables = append(sortMergeTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.TiDBBroadCastJoin, h.HintBCJ:
bcTables = append(bcTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintShuffleJoin:
shuffleJoinTables = append(shuffleJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.TiDBIndexNestedLoopJoin, h.HintINLJ:
inljTables = append(inljTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintINLHJ:
inlhjTables = append(inlhjTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintINLMJ:
inlmjTables = append(inlmjTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.TiDBHashJoin, h.HintHJ:
hashJoinTables = append(hashJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintNoHashJoin:
noHashJoinTables = append(noHashJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintNoMergeJoin:
noMergeJoinTables = append(noMergeJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintNoIndexJoin:
noIndexJoinTables = append(noIndexJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintNoIndexHashJoin:
noIndexHashJoinTables = append(noIndexHashJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintNoIndexMergeJoin:
noIndexMergeJoinTables = append(noIndexMergeJoinTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintMPP1PhaseAgg:
aggHints.PreferAggType |= h.PreferMPP1PhaseAgg
case h.HintMPP2PhaseAgg:
aggHints.PreferAggType |= h.PreferMPP2PhaseAgg
case h.HintHashJoinBuild:
hjBuildTables = append(hjBuildTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintHashJoinProbe:
hjProbeTables = append(hjProbeTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintHashAgg:
aggHints.PreferAggType |= h.PreferHashAgg
case h.HintStreamAgg:
aggHints.PreferAggType |= h.PreferStreamAgg
case h.HintAggToCop:
aggHints.PreferAggToCop = true
case h.HintUseIndex, h.HintIgnoreIndex, h.HintForceIndex, h.HintOrderIndex, h.HintNoOrderIndex:
dbName := hint.Tables[0].DBName
if dbName.L == "" {
dbName = model.NewCIStr(b.ctx.GetSessionVars().CurrentDB)
}
var hintType ast.IndexHintType
switch hint.HintName.L {
case h.HintUseIndex:
hintType = ast.HintUse
case h.HintIgnoreIndex:
hintType = ast.HintIgnore
case h.HintForceIndex:
hintType = ast.HintForce
case h.HintOrderIndex:
hintType = ast.HintOrderIndex
case h.HintNoOrderIndex:
hintType = ast.HintNoOrderIndex
}
indexHintList = append(indexHintList, h.HintedIndex{
DBName: dbName,
TblName: hint.Tables[0].TableName,
Partitions: hint.Tables[0].PartitionList,
IndexHint: &ast.IndexHint{
IndexNames: hint.Indexes,
HintType: hintType,
HintScope: ast.HintForScan,
},
})
case h.HintReadFromStorage:
switch hint.HintData.(model.CIStr).L {
case h.HintTiFlash:
tiflashTables = append(tiflashTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
case h.HintTiKV:
tikvTables = append(tikvTables, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
}
case h.HintIndexMerge:
dbName := hint.Tables[0].DBName
if dbName.L == "" {
dbName = model.NewCIStr(b.ctx.GetSessionVars().CurrentDB)
}
indexMergeHintList = append(indexMergeHintList, h.HintedIndex{
DBName: dbName,
TblName: hint.Tables[0].TableName,
Partitions: hint.Tables[0].PartitionList,
IndexHint: &ast.IndexHint{
IndexNames: hint.Indexes,
HintType: ast.HintUse,
HintScope: ast.HintForScan,
},
})
case h.HintTimeRange:
timeRangeHint = hint.HintData.(ast.HintTimeRange)
case h.HintLimitToCop:
preferLimitToCop = true
case h.HintMerge:
if hint.Tables != nil {
b.ctx.GetSessionVars().StmtCtx.SetHintWarning("The MERGE hint is not used correctly, maybe it inputs a table name.")
continue
}
cteMerge = true
case h.HintLeading:
if leadingHintCnt == 0 {
leadingJoinOrder = append(leadingJoinOrder, h.TableNames2HintTableInfo(currentDB, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel, warnHandler)...)
}
leadingHintCnt++
case h.HintSemiJoinRewrite:
if b.subQueryCtx != handlingExistsSubquery {
b.ctx.GetSessionVars().StmtCtx.SetHintWarning("The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause.")
continue
}
b.subQueryHintFlags |= h.HintFlagSemiJoinRewrite
case h.HintNoDecorrelate:
if b.subQueryCtx == notHandlingSubquery {
b.ctx.GetSessionVars().StmtCtx.SetHintWarning("NO_DECORRELATE() is inapplicable because it's not in an IN subquery, an EXISTS subquery, an ANY/ALL/SOME subquery or a scalar subquery.")
continue
}
b.subQueryHintFlags |= h.HintFlagNoDecorrelate
default:
// ignore hints that not implemented
}
}
if leadingHintCnt > 1 || (leadingHintCnt > 0 && b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder) {
// If there are more leading hints or the straight_join hint existes, all leading hints will be invalid.
leadingJoinOrder = leadingJoinOrder[:0]
if leadingHintCnt > 1 {
b.ctx.GetSessionVars().StmtCtx.SetHintWarning("We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid")
} else if b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder {
b.ctx.GetSessionVars().StmtCtx.SetHintWarning("We can only use the straight_join hint, when we use the leading hint and straight_join hint at the same time, all leading hints will be invalid")
}
}
b.tableHintInfo = append(b.tableHintInfo, &h.PlanHints{
SortMergeJoin: sortMergeTables,
BroadcastJoin: bcTables,
ShuffleJoin: shuffleJoinTables,
IndexJoin: h.IndexJoinHints{INLJTables: inljTables, INLHJTables: inlhjTables, INLMJTables: inlmjTables},
NoIndexJoin: h.IndexJoinHints{INLJTables: noIndexJoinTables, INLHJTables: noIndexHashJoinTables, INLMJTables: noIndexMergeJoinTables},
HashJoin: hashJoinTables,
NoHashJoin: noHashJoinTables,
NoMergeJoin: noMergeJoinTables,
IndexHintList: indexHintList,
TiFlashTables: tiflashTables,
TiKVTables: tikvTables,
Agg: aggHints,
IndexMergeHintList: indexMergeHintList,
TimeRangeHint: timeRangeHint,
PreferLimitToCop: preferLimitToCop,
CTEMerge: cteMerge,
LeadingJoinOrder: leadingJoinOrder,
HJBuild: hjBuildTables,
HJProbe: hjProbeTables,
})
planHints, subQueryHintFlags, err := h.ParsePlanHints(hints, currentLevel, currentDB,
b.hintProcessor, b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder,
b.subQueryCtx == handlingExistsSubquery, b.subQueryCtx == notHandlingSubquery, warnHandler)
if err != nil {
return
}
b.tableHintInfo = append(b.tableHintInfo, planHints)
b.subQueryHintFlags |= subQueryHintFlags
}

func (b *PlanBuilder) popVisitInfo() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ type PlanBuilder struct {
subQueryCtx subQueryCtx
// subQueryHintFlags stores subquery related hints that are set and applicable in the query block.
// It's for returning information to buildSubquery().
subQueryHintFlags uint64
subQueryHintFlags uint64 // TODO: move this field to hint.PlanHints

// disableSubQueryPreprocessing indicates whether to pre-process uncorrelated sub-queries in rewriting stage.
disableSubQueryPreprocessing bool
Expand Down
Loading