From 3b6f49f908db9e683ec173ebee6cedca0811a4ed Mon Sep 17 00:00:00 2001 From: Will DeVries Date: Wed, 3 Sep 2025 21:18:55 -0700 Subject: [PATCH 1/3] Fix issue with getPotentialEqOrInColOffset --- pkg/util/ranger/detacher.go | 74 +++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/pkg/util/ranger/detacher.go b/pkg/util/ranger/detacher.go index b2df0a6f3ba47..7e9e7864faf03 100644 --- a/pkg/util/ranger/detacher.go +++ b/pkg/util/ranger/detacher.go @@ -129,51 +129,43 @@ func getPotentialEqOrInColOffset(sctx *rangerctx.RangerContext, expr expression. } return offset case ast.EQ, ast.NullEQ, ast.LE, ast.GE, ast.LT, ast.GT: - if c, ok := f.GetArgs()[0].(*expression.Column); ok { - if c.RetType.EvalType() == types.ETString && !collate.CompatibleCollate(c.RetType.GetCollate(), collation) { - return -1 - } - if (f.FuncName.L == ast.LT || f.FuncName.L == ast.GT) && c.RetType.EvalType() != types.ETInt { + var constVal *expression.Constant + c, ok := f.GetArgs()[0].(*expression.Column) + idx_const := 1 + if !ok { + idx_const = 0 + if c, ok = f.GetArgs()[1].(*expression.Column); !ok { return -1 } - if constVal, ok := f.GetArgs()[1].(*expression.Constant); ok { - val, err := constVal.Eval(evalCtx, chunk.Row{}) - intest.AssertFunc(func() bool { - if sctx.ExprCtx.ConnectionID() == 0 { - return sctx.RegardNULLAsPoint - } - return true - }) - if err != nil || (!sctx.RegardNULLAsPoint && val.IsNull()) || (f.FuncName.L == ast.NullEQ && val.IsNull()) { - // treat col<=>null as range scan instead of point get to avoid incorrect results - // when nullable unique index has multiple matches for filter x is null - return -1 - } - for i, col := range cols { - // When cols are a generated expression col, compare them in terms of virtual expr. - if col.EqualByExprAndID(evalCtx, c) { - return i - } - } - } } - if c, ok := f.GetArgs()[1].(*expression.Column); ok { - if c.RetType.EvalType() == types.ETString && !collate.CompatibleCollate(c.RetType.GetCollate(), collation) { - return -1 - } - if (f.FuncName.L == ast.LT || f.FuncName.L == ast.GT) && c.RetType.EvalType() != types.ETInt { - return -1 + + if c.RetType.EvalType() == types.ETString && !collate.CompatibleCollate(c.RetType.GetCollate(), collation) { + return -1 + } + if (f.FuncName.L == ast.LT || f.FuncName.L == ast.GT) && c.RetType.EvalType() != types.ETInt { + return -1 + } + + if constVal, ok = f.GetArgs()[idx_const].(*expression.Constant); !ok { + return -1 + } + + val, err := constVal.Eval(evalCtx, chunk.Row{}) + intest.AssertFunc(func() bool { + if sctx.ExprCtx.ConnectionID() == 0 { + return sctx.RegardNULLAsPoint } - if constVal, ok := f.GetArgs()[0].(*expression.Constant); ok { - val, err := constVal.Eval(evalCtx, chunk.Row{}) - if err != nil || (!sctx.RegardNULLAsPoint && val.IsNull()) { - return -1 - } - for i, col := range cols { - if col.EqualColumn(c) { - return i - } - } + return true + }) + if err != nil || (!sctx.RegardNULLAsPoint && val.IsNull()) || (f.FuncName.L == ast.NullEQ && val.IsNull()) { + // treat col<=>null as range scan instead of point get to avoid incorrect results + // when nullable unique index has multiple matches for filter x is null + return -1 + } + for i, col := range cols { + // When cols are a generated expression col, compare them in terms of virtual expr. + if col.EqualByExprAndID(evalCtx, c) { + return i } } case ast.In: From a371eace0c8f8283184b479630ae656a58c8f724 Mon Sep 17 00:00:00 2001 From: Will DeVries Date: Fri, 26 Sep 2025 16:50:49 -0700 Subject: [PATCH 2/3] Remove unused failpoint. --- pkg/planner/core/exhaust_physical_plans.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pkg/planner/core/exhaust_physical_plans.go b/pkg/planner/core/exhaust_physical_plans.go index d86a344aa57b6..7e4baa00dbddd 100644 --- a/pkg/planner/core/exhaust_physical_plans.go +++ b/pkg/planner/core/exhaust_physical_plans.go @@ -1107,11 +1107,6 @@ func buildIndexJoinInner2TableScan( lastColMng = indexJoinResult.lastColManager } joins = make([]base.PhysicalPlan, 0, 3) - failpoint.Inject("MockOnlyEnableIndexHashJoin", func(val failpoint.Value) { - if val.(bool) && !p.SCtx().GetSessionVars().InRestrictedSQL { - failpoint.Return(constructIndexHashJoin(p, prop, outerIdx, innerTask, nil, keyOff2IdxOff, path, lastColMng)) - } - }) joins = append(joins, constructIndexJoin(p, prop, outerIdx, innerTask, ranges, keyOff2IdxOff, path, lastColMng, true)...) // We can reuse the `innerTask` here since index nested loop hash join // do not need the inner child to promise the order. @@ -1148,11 +1143,6 @@ func buildIndexJoinInner2IndexScan( joins = make([]base.PhysicalPlan, 0, 3) rangeInfo, maxOneRow := indexJoinPathGetRangeInfoAndMaxOneRow(p.SCtx(), outerJoinKeys, indexJoinResult) innerTask := constructInnerIndexScanTask(p, prop, wrapper, indexJoinResult.chosenPath, indexJoinResult.chosenRanges.Range(), indexJoinResult.chosenRemained, indexJoinResult.idxOff2KeyOff, rangeInfo, false, false, avgInnerRowCnt, maxOneRow) - failpoint.Inject("MockOnlyEnableIndexHashJoin", func(val failpoint.Value) { - if val.(bool) && !p.SCtx().GetSessionVars().InRestrictedSQL && innerTask != nil { - failpoint.Return(constructIndexHashJoin(p, prop, outerIdx, innerTask, indexJoinResult.chosenRanges, keyOff2IdxOff, indexJoinResult.chosenPath, indexJoinResult.lastColManager)) - } - }) if innerTask != nil { joins = append(joins, constructIndexJoin(p, prop, outerIdx, innerTask, indexJoinResult.chosenRanges, keyOff2IdxOff, indexJoinResult.chosenPath, indexJoinResult.lastColManager, true)...) // We can reuse the `innerTask` here since index nested loop hash join @@ -2667,12 +2657,6 @@ func tryToGetMppHashJoin(super base.LogicalPlan, prop *property.PhysicalProperty // If the hint is not figured, we will pick all candidates. func exhaustPhysicalPlans4LogicalJoin(super base.LogicalPlan, prop *property.PhysicalProperty) ([]base.PhysicalPlan, bool, error) { ge, p := base.GetGEAndLogicalOp[*logicalop.LogicalJoin](super) - failpoint.Inject("MockOnlyEnableIndexHashJoin", func(val failpoint.Value) { - if val.(bool) && !p.SCtx().GetSessionVars().InRestrictedSQL { - indexJoins, _ := tryToGetIndexJoin(p, prop) - failpoint.Return(indexJoins, true, nil) - } - }) if !isJoinHintSupportedInMPPMode(p.PreferJoinType) { if hasMPPJoinHints(p.PreferJoinType) { From cb9581edd6d0876ffae23d41b049ebbd79e48699 Mon Sep 17 00:00:00 2001 From: Will DeVries Date: Tue, 3 Feb 2026 13:14:16 -0800 Subject: [PATCH 3/3] Fix variable name. --- pkg/util/ranger/detacher.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/util/ranger/detacher.go b/pkg/util/ranger/detacher.go index 7e9e7864faf03..4eb84af912b17 100644 --- a/pkg/util/ranger/detacher.go +++ b/pkg/util/ranger/detacher.go @@ -131,9 +131,9 @@ func getPotentialEqOrInColOffset(sctx *rangerctx.RangerContext, expr expression. case ast.EQ, ast.NullEQ, ast.LE, ast.GE, ast.LT, ast.GT: var constVal *expression.Constant c, ok := f.GetArgs()[0].(*expression.Column) - idx_const := 1 + idxConst := 1 if !ok { - idx_const = 0 + idxConst = 0 if c, ok = f.GetArgs()[1].(*expression.Column); !ok { return -1 } @@ -146,7 +146,7 @@ func getPotentialEqOrInColOffset(sctx *rangerctx.RangerContext, expr expression. return -1 } - if constVal, ok = f.GetArgs()[idx_const].(*expression.Constant); !ok { + if constVal, ok = f.GetArgs()[idxConst].(*expression.Constant); !ok { return -1 }