diff --git a/cmd/explaintest/r/collation_check_use_collation.result b/cmd/explaintest/r/collation_check_use_collation.result index ffd787a4cef43..84f0f583ae796 100644 --- a/cmd/explaintest/r/collation_check_use_collation.result +++ b/cmd/explaintest/r/collation_check_use_collation.result @@ -22,4 +22,13 @@ a select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); a_col a +drop table if exists tbl_2; +create table tbl_2 ( col_20 bigint not null , col_21 smallint not null , col_22 decimal(24,10) default null , col_23 tinyint default 71 not null , col_24 bigint not null , col_25 tinyint default 18 , col_26 varchar(330) collate utf8_bin not null , col_27 char(77) collate utf8mb4_unicode_ci , col_28 char(46) collate utf8_general_ci not null , col_29 smallint unsigned not null , primary key idx_13 ( col_27(5) ) , key idx_14 ( col_24 ) , unique key idx_15 ( col_23,col_21,col_28,col_29,col_24 ) ) collate utf8_bin ; +insert ignore into tbl_2 values ( 5888267793391993829,5371,94.63,-109,5728076076919247337,89,'WUicqUTgdGJcjbC','SapBPqczTWWSN','xUSwH',49462 ); +select col_25 from tbl_2 where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +89 +select col_25 from tbl_2 use index(primary) where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +col_25 +89 use test diff --git a/cmd/explaintest/t/collation_check_use_collation.test b/cmd/explaintest/t/collation_check_use_collation.test index 67e75f32e38f9..0fd8f373f8e76 100644 --- a/cmd/explaintest/t/collation_check_use_collation.test +++ b/cmd/explaintest/t/collation_check_use_collation.test @@ -19,5 +19,11 @@ select a as a_col from t where t.a <= all (select a collate utf8mb4_general_ci f select a as a_col from t where t.a <= any (select a collate utf8mb4_general_ci from t1); select a as a_col from t where t.a = (select a collate utf8mb4_general_ci from t1); +drop table if exists tbl_2; +create table tbl_2 ( col_20 bigint not null , col_21 smallint not null , col_22 decimal(24,10) default null , col_23 tinyint default 71 not null , col_24 bigint not null , col_25 tinyint default 18 , col_26 varchar(330) collate utf8_bin not null , col_27 char(77) collate utf8mb4_unicode_ci , col_28 char(46) collate utf8_general_ci not null , col_29 smallint unsigned not null , primary key idx_13 ( col_27(5) ) , key idx_14 ( col_24 ) , unique key idx_15 ( col_23,col_21,col_28,col_29,col_24 ) ) collate utf8_bin ; +insert ignore into tbl_2 values ( 5888267793391993829,5371,94.63,-109,5728076076919247337,89,'WUicqUTgdGJcjbC','SapBPqczTWWSN','xUSwH',49462 ); +select col_25 from tbl_2 where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); +select col_25 from tbl_2 use index(primary) where ( tbl_2.col_27 > 'nSWYrpTH' or not( tbl_2.col_27 between 'CsWIuxlSjU' and 'SfwoyjUEzgg' ) ) and ( tbl_2.col_23 <= -95); + # cleanup environment use test diff --git a/util/ranger/detacher.go b/util/ranger/detacher.go index 6d9b036f7200c..7f64647fb792c 100644 --- a/util/ranger/detacher.go +++ b/util/ranger/detacher.go @@ -529,11 +529,12 @@ func ExtractEqAndInCondition(sctx sessionctx.Context, conditions []expression.Ex } // Multiple Eq/In conditions for one column in CNF, apply intersection on them // Lazily compute the points for the previously visited Eq/In + collator := collate.GetCollator(cols[offset].GetType().Collate) if mergedAccesses[offset] == nil { mergedAccesses[offset] = accesses[offset] - points[offset] = rb.build(accesses[offset]) + points[offset] = rb.build(accesses[offset], collator) } - points[offset] = rb.intersection(points[offset], rb.build(cond), collate.GetCollator(cols[offset].GetType().Collate)) + points[offset] = rb.intersection(points[offset], rb.build(cond, collator), collator) if len(points[offset]) == 0 { // Early termination if false expression found if expression.MaybeOverOptimized4PlanCache(sctx, conditions) { // cannot return an empty-range for plan-cache since the range may become non-empty as parameters change @@ -665,7 +666,7 @@ func (d *rangeDetacher) detachDNFCondAndBuildRangeForIndex(condition *expression hasResidual = true firstColumnChecker.shouldReserve = d.lengths[0] != types.UnspecifiedLength } - points := rb.build(item) + points := rb.build(item, collate.GetCollator(newTpSlice[0].Collate)) ranges, err := points2Ranges(d.sctx, points, newTpSlice[0]) if err != nil { return nil, nil, nil, false, errors.Trace(err) diff --git a/util/ranger/points.go b/util/ranger/points.go index 2d2efc3c0f9c9..b4fc37bac5e20 100644 --- a/util/ranger/points.go +++ b/util/ranger/points.go @@ -185,12 +185,12 @@ type builder struct { sc *stmtctx.StatementContext } -func (r *builder) build(expr expression.Expression) []*point { +func (r *builder) build(expr expression.Expression, collator collate.Collator) []*point { switch x := expr.(type) { case *expression.Column: return r.buildFromColumn(x) case *expression.ScalarFunction: - return r.buildFromScalarFunc(x) + return r.buildFromScalarFunc(x, collator) case *expression.Constant: return r.buildFromConstant(x) } @@ -762,16 +762,14 @@ func (r *builder) buildFromNot(expr *expression.ScalarFunction) []*point { return getFullRange() } -func (r *builder) buildFromScalarFunc(expr *expression.ScalarFunction) []*point { - _, coll := expr.CharsetAndCollation() - collator := collate.GetCollator(coll) +func (r *builder) buildFromScalarFunc(expr *expression.ScalarFunction, collator collate.Collator) []*point { switch op := expr.FuncName.L; op { case ast.GE, ast.GT, ast.LT, ast.LE, ast.EQ, ast.NE, ast.NullEQ: return r.buildFromBinOp(expr) case ast.LogicAnd: - return r.intersection(r.build(expr.GetArgs()[0]), r.build(expr.GetArgs()[1]), collator) + return r.intersection(r.build(expr.GetArgs()[0], collator), r.build(expr.GetArgs()[1], collator), collator) case ast.LogicOr: - return r.union(r.build(expr.GetArgs()[0]), r.build(expr.GetArgs()[1]), collator) + return r.union(r.build(expr.GetArgs()[0], collator), r.build(expr.GetArgs()[1], collator), collator) case ast.IsTruthWithoutNull: return r.buildFromIsTrue(expr, 0, false) case ast.IsTruthWithNull: diff --git a/util/ranger/ranger.go b/util/ranger/ranger.go index b0ffd1bc5b6f3..0e5e9988062b3 100644 --- a/util/ranger/ranger.go +++ b/util/ranger/ranger.go @@ -312,7 +312,8 @@ func buildColumnRange(accessConditions []expression.Expression, sctx sessionctx. rb := builder{sc: sctx.GetSessionVars().StmtCtx} rangePoints := getFullRange() for _, cond := range accessConditions { - rangePoints = rb.intersection(rangePoints, rb.build(cond), collate.GetCollator(tp.Collate)) + collator := collate.GetCollator(tp.Collate) + rangePoints = rb.intersection(rangePoints, rb.build(cond, collator), collator) if rb.err != nil { return nil, errors.Trace(rb.err) } @@ -372,7 +373,7 @@ func (d *rangeDetacher) buildCNFIndexRange(newTp []*types.FieldType, } for i := 0; i < eqAndInCount; i++ { // Build ranges for equal or in access conditions. - point := rb.build(accessCondition[i]) + point := rb.build(accessCondition[i], collate.GetCollator(newTp[i].Collate)) if rb.err != nil { return nil, errors.Trace(rb.err) } @@ -388,7 +389,8 @@ func (d *rangeDetacher) buildCNFIndexRange(newTp []*types.FieldType, rangePoints := getFullRange() // Build rangePoints for non-equal access conditions. for i := eqAndInCount; i < len(accessCondition); i++ { - rangePoints = rb.intersection(rangePoints, rb.build(accessCondition[i]), collate.GetCollator(newTp[eqAndInCount].Collate)) + collator := collate.GetCollator(newTp[eqAndInCount].Collate) + rangePoints = rb.intersection(rangePoints, rb.build(accessCondition[i], collator), collator) if rb.err != nil { return nil, errors.Trace(rb.err) }