Skip to content

Commit 07ccf7c

Browse files
authoredJan 23, 2025··
planner: remove redundant branches in the OR list (#58962)
close #58998
1 parent ade745f commit 07ccf7c

File tree

5 files changed

+162
-6
lines changed

5 files changed

+162
-6
lines changed
 

‎pkg/planner/core/rule_predicate_simplification.go

+46
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ func splitCNF(conditions []expression.Expression) []expression.Expression {
186186
func applyPredicateSimplification(sctx base.PlanContext, predicates []expression.Expression) []expression.Expression {
187187
simplifiedPredicate := shortCircuitLogicalConstants(sctx, predicates)
188188
simplifiedPredicate = mergeInAndNotEQLists(sctx, simplifiedPredicate)
189+
removeRedundantORBranch(sctx, simplifiedPredicate)
189190
pruneEmptyORBranches(sctx, simplifiedPredicate)
190191
simplifiedPredicate = splitCNF(simplifiedPredicate)
191192
return simplifiedPredicate
@@ -424,6 +425,51 @@ func shortCircuitLogicalConstants(sctx base.PlanContext, predicates []expression
424425
return finalResult
425426
}
426427

428+
// removeRedundantORBranch recursively iterates over a list of predicates, try to find OR lists and remove redundant in
429+
// each OR list.
430+
// It modifies the input slice in place.
431+
func removeRedundantORBranch(sctx base.PlanContext, predicates []expression.Expression) {
432+
for i, predicate := range predicates {
433+
predicates[i] = recursiveRemoveRedundantORBranch(sctx, predicate)
434+
}
435+
}
436+
437+
func recursiveRemoveRedundantORBranch(sctx base.PlanContext, predicate expression.Expression) expression.Expression {
438+
_, tp := FindPredicateType(sctx, predicate)
439+
if tp != orPredicate {
440+
return predicate
441+
}
442+
orFunc := predicate.(*expression.ScalarFunction)
443+
orList := expression.SplitDNFItems(orFunc)
444+
445+
dedupMap := make(map[string]struct{}, len(orList))
446+
newORList := make([]expression.Expression, 0, len(orList))
447+
448+
for _, orItem := range orList {
449+
_, tp := FindPredicateType(sctx, orItem)
450+
// 1. If it's an AND predicate, we recursively call removeRedundantORBranch() on it.
451+
if tp == andPredicate {
452+
andFunc := orItem.(*expression.ScalarFunction)
453+
andList := expression.SplitCNFItems(andFunc)
454+
removeRedundantORBranch(sctx, andList)
455+
newORList = append(newORList, expression.ComposeCNFCondition(sctx.GetExprCtx(), andList...))
456+
} else {
457+
// 2. Otherwise, we check if it's a duplicate predicate by checking HashCode().
458+
hashCode := string(orItem.HashCode())
459+
// 2-1. If it's not a duplicate, we need to keep this predicate.
460+
if _, ok := dedupMap[hashCode]; !ok {
461+
dedupMap[hashCode] = struct{}{}
462+
newORList = append(newORList, orItem)
463+
} else if expression.IsMutableEffectsExpr(orItem) {
464+
// 2-2. If it's a duplicate, but it's nondeterministic or has side effects, we also need to keep it.
465+
newORList = append(newORList, orItem)
466+
}
467+
// 2-3. Otherwise, we remove it.
468+
}
469+
}
470+
return expression.ComposeDNFCondition(sctx.GetExprCtx(), newORList...)
471+
}
472+
427473
// Name implements base.LogicalOptRule.<1st> interface.
428474
func (*PredicateSimplification) Name() string {
429475
return "predicate_simplification"

‎tests/integrationtest/r/executor/partition/partition_boundaries.result

+4-4
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ a b
478478
explain format='brief' SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2;
479479
id estRows task access object operator info
480480
TableReader 3.00 root partition:p0,p1,p2 data:Selection
481-
└─Selection 3.00 cop[tikv] or(eq(executor__partition__partition_boundaries.t.a, -1), or(eq(executor__partition__partition_boundaries.t.a, 0), or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2))))
481+
└─Selection 3.00 cop[tikv] or(or(eq(executor__partition__partition_boundaries.t.a, -1), eq(executor__partition__partition_boundaries.t.a, 0)), or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2)))
482482
└─TableFullScan 7.00 cop[tikv] table:t keep order:false
483483
SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2;
484484
a b
@@ -563,7 +563,7 @@ a b
563563
explain format='brief' SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4;
564564
id estRows task access object operator info
565565
TableReader 5.00 root partition:p0,p1,p2,p3,p4 data:Selection
566-
└─Selection 5.00 cop[tikv] or(or(eq(executor__partition__partition_boundaries.t.a, -1), eq(executor__partition__partition_boundaries.t.a, 0)), or(or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2)), or(eq(executor__partition__partition_boundaries.t.a, 3), eq(executor__partition__partition_boundaries.t.a, 4))))
566+
└─Selection 5.00 cop[tikv] or(or(eq(executor__partition__partition_boundaries.t.a, -1), or(eq(executor__partition__partition_boundaries.t.a, 0), eq(executor__partition__partition_boundaries.t.a, 1))), or(eq(executor__partition__partition_boundaries.t.a, 2), or(eq(executor__partition__partition_boundaries.t.a, 3), eq(executor__partition__partition_boundaries.t.a, 4))))
567567
└─TableFullScan 7.00 cop[tikv] table:t keep order:false
568568
SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4;
569569
a b
@@ -644,7 +644,7 @@ a b
644644
explain format='brief' SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4 OR a = 5 OR a = 6;
645645
id estRows task access object operator info
646646
TableReader 7.00 root partition:all data:Selection
647-
└─Selection 7.00 cop[tikv] or(or(eq(executor__partition__partition_boundaries.t.a, -1), or(eq(executor__partition__partition_boundaries.t.a, 0), eq(executor__partition__partition_boundaries.t.a, 1))), or(or(eq(executor__partition__partition_boundaries.t.a, 2), eq(executor__partition__partition_boundaries.t.a, 3)), or(eq(executor__partition__partition_boundaries.t.a, 4), or(eq(executor__partition__partition_boundaries.t.a, 5), eq(executor__partition__partition_boundaries.t.a, 6)))))
647+
└─Selection 7.00 cop[tikv] or(or(or(eq(executor__partition__partition_boundaries.t.a, -1), eq(executor__partition__partition_boundaries.t.a, 0)), or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2))), or(or(eq(executor__partition__partition_boundaries.t.a, 3), eq(executor__partition__partition_boundaries.t.a, 4)), or(eq(executor__partition__partition_boundaries.t.a, 5), eq(executor__partition__partition_boundaries.t.a, 6))))
648648
└─TableFullScan 7.00 cop[tikv] table:t keep order:false
649649
SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4 OR a = 5 OR a = 6;
650650
a b
@@ -686,7 +686,7 @@ a b
686686
explain format='brief' SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4 OR a = 5 OR a = 6 OR a = 7;
687687
id estRows task access object operator info
688688
TableReader 7.00 root partition:all data:Selection
689-
└─Selection 7.00 cop[tikv] or(or(eq(executor__partition__partition_boundaries.t.a, -1), or(eq(executor__partition__partition_boundaries.t.a, 0), or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2)))), or(or(eq(executor__partition__partition_boundaries.t.a, 3), eq(executor__partition__partition_boundaries.t.a, 4)), or(eq(executor__partition__partition_boundaries.t.a, 5), or(eq(executor__partition__partition_boundaries.t.a, 6), eq(executor__partition__partition_boundaries.t.a, 7)))))
689+
└─Selection 7.00 cop[tikv] or(or(or(eq(executor__partition__partition_boundaries.t.a, -1), eq(executor__partition__partition_boundaries.t.a, 0)), or(eq(executor__partition__partition_boundaries.t.a, 1), eq(executor__partition__partition_boundaries.t.a, 2))), or(or(eq(executor__partition__partition_boundaries.t.a, 3), eq(executor__partition__partition_boundaries.t.a, 4)), or(eq(executor__partition__partition_boundaries.t.a, 5), or(eq(executor__partition__partition_boundaries.t.a, 6), eq(executor__partition__partition_boundaries.t.a, 7)))))
690690
└─TableFullScan 7.00 cop[tikv] table:t keep order:false
691691
SELECT * FROM t WHERE 1 = 0 OR a = -1 OR a = 0 OR a = 1 OR a = 2 OR a = 3 OR a = 4 OR a = 5 OR a = 6 OR a = 7;
692692
a b

‎tests/integrationtest/r/planner/core/casetest/predicate_simplification.result

+84
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,87 @@ count(*)
571571
SELECT count(*) FROM t1 WHERE (1 = 0 AND a1 = 1) OR (b1 = 2);
572572
count(*)
573573
1
574+
drop table if exists t1;
575+
create table t1 (a int, b decimal(65,30), c int);
576+
explain format=brief select * from t1 where a = 1 or a = 2 or a = 5 or a = 5 or a = 5;
577+
id estRows task access object operator info
578+
TableReader 30.00 root data:Selection
579+
└─Selection 30.00 cop[tikv] or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 2), eq(planner__core__casetest__predicate_simplification.t1.a, 5)))
580+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
581+
explain format=brief select * from t1 where a = 1 or a = 2 or a = 5 or a = 5 or a = 5 or b = 1.1 or b = 2.2 or b = 3.3 or b = 3.3;
582+
id estRows task access object operator info
583+
TableReader 59.91 root data:Selection
584+
└─Selection 59.91 cop[tikv] or(or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 2), eq(planner__core__casetest__predicate_simplification.t1.a, 5))), or(eq(planner__core__casetest__predicate_simplification.t1.b, 1.1), or(eq(planner__core__casetest__predicate_simplification.t1.b, 2.2), eq(planner__core__casetest__predicate_simplification.t1.b, 3.3))))
585+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
586+
explain format=brief select * from t1 where a = 1 and (b = 1.1 or b = 2.2 or b = 3.3 or b = 3.3);
587+
id estRows task access object operator info
588+
TableReader 0.03 root data:Selection
589+
└─Selection 0.03 cop[tikv] eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.b, 1.1), or(eq(planner__core__casetest__predicate_simplification.t1.b, 2.2), eq(planner__core__casetest__predicate_simplification.t1.b, 3.3)))
590+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
591+
explain format=brief select * from t1 where a = 1 or (b = 1.1 and (a = 1 or a = 2 or a = 5 or a = 5 or a = 5));
592+
id estRows task access object operator info
593+
TableReader 10.03 root data:Selection
594+
└─Selection 10.03 cop[tikv] or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), and(eq(planner__core__casetest__predicate_simplification.t1.b, 1.1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 2), eq(planner__core__casetest__predicate_simplification.t1.a, 5)))))
595+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
596+
explain format=brief select * from t1 where (a = 1 and (b = 2.2 or (c = 1 and (b = 1 or b = 1)))) or (b = 1.1 and b = 1.1 and (a = 1 or a = 2 or a = 5 or a = 5 or a = 5));
597+
id estRows task access object operator info
598+
TableReader 0.04 root data:Selection
599+
└─Selection 0.04 cop[tikv] or(and(eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.b, 2.2), and(eq(planner__core__casetest__predicate_simplification.t1.c, 1), eq(planner__core__casetest__predicate_simplification.t1.b, 1)))), and(eq(planner__core__casetest__predicate_simplification.t1.b, 1.1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), or(eq(planner__core__casetest__predicate_simplification.t1.a, 2), eq(planner__core__casetest__predicate_simplification.t1.a, 5)))))
600+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
601+
explain format=brief select * from t1 where (c = 10 or (b + 1 > 10 and (a + 1 < 5 or a + 1 < 5 or a = 20))) and c + 1 < 10 and (a = 1 or a = 2 or a = 5 or a = 5 or b = 5 or b = 5);
602+
id estRows task access object operator info
603+
TableReader 20.48 root data:Selection
604+
└─Selection 20.48 cop[tikv] lt(plus(planner__core__casetest__predicate_simplification.t1.c, 1), 10), or(eq(planner__core__casetest__predicate_simplification.t1.c, 10), and(gt(plus(planner__core__casetest__predicate_simplification.t1.b, 1), 10), or(lt(plus(planner__core__casetest__predicate_simplification.t1.a, 1), 5), eq(planner__core__casetest__predicate_simplification.t1.a, 20)))), or(or(eq(planner__core__casetest__predicate_simplification.t1.a, 1), eq(planner__core__casetest__predicate_simplification.t1.a, 2)), or(eq(planner__core__casetest__predicate_simplification.t1.a, 5), eq(planner__core__casetest__predicate_simplification.t1.b, 5)))
605+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
606+
explain format=brief select * from t1 where (rand() * 10 = 1) or (rand() * 10 = 1);
607+
id estRows task access object operator info
608+
Selection 8000.00 root or(eq(mul(rand(), 10), 1), eq(mul(rand(), 10), 1))
609+
└─TableReader 10000.00 root data:TableFullScan
610+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
611+
explain format=brief select * from t1 where (@a:=@a+1) or (@a:=@a+1);
612+
id estRows task access object operator info
613+
Selection 8000.00 root or(istrue_with_null(setvar("a", plus(cast(getvar("a"), double BINARY), 1))), istrue_with_null(setvar("a", plus(getvar("a"), 1))))
614+
└─TableReader 10000.00 root data:TableFullScan
615+
└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
616+
drop table if exists t2;
617+
create table t2 (a datetime(6), b timestamp(6), index ia(a), index iab(a,b));
618+
explain format=brief select * from t2 where a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00';
619+
id estRows task access object operator info
620+
IndexReader 10.00 root index:IndexRangeScan
621+
└─IndexRangeScan 10.00 cop[tikv] table:t2, index:iab(a, b) range:[2025-01-01 00:00:00.000000,2025-01-01 00:00:00.000000], keep order:false, stats:pseudo
622+
explain format=brief select * from t2 where (a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00') and (b = '2025-01-01 00:00:00' or b = '2025-01-01 00:00:00' or b = '2025-01-01 00:00:00');
623+
id estRows task access object operator info
624+
IndexReader 0.10 root index:IndexRangeScan
625+
└─IndexRangeScan 0.10 cop[tikv] table:t2, index:iab(a, b) range:[2025-01-01 00:00:00.000000 2025-01-01 00:00:00.000000,2025-01-01 00:00:00.000000 2025-01-01 00:00:00.000000], keep order:false, stats:pseudo
626+
drop table if exists t3;
627+
create table t3 (a varchar(10) collate utf8mb4_general_ci, b varchar(10) collate utf8mb4_bin, index ia(a), index ib(b));
628+
explain format=brief select * from t3 where a = 'a' or a = 'a' or a = 'A';
629+
id estRows task access object operator info
630+
IndexLookUp 10.00 root
631+
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t3, index:ia(a) range:["\x00A","\x00A"], keep order:false, stats:pseudo
632+
└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t3 keep order:false, stats:pseudo
633+
explain format=brief select * from t3 where a = 'a' or a = 'a' or a = 'A' or b = _utf8mb4'b' or b = _latin1'b' or b = 'B';
634+
id estRows task access object operator info
635+
IndexMerge 29.98 root type: union
636+
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t3, index:ia(a) range:["\x00A","\x00A"], keep order:false, stats:pseudo
637+
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t3, index:ia(a) range:["\x00A","\x00A"], keep order:false, stats:pseudo
638+
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t3, index:ib(b) range:["b","b"], keep order:false, stats:pseudo
639+
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t3, index:ib(b) range:["B","B"], keep order:false, stats:pseudo
640+
└─TableRowIDScan(Probe) 29.98 cop[tikv] table:t3 keep order:false, stats:pseudo
641+
explain format=brief select * from t3 where a = _utf8mb4'a' collate utf8mb4_unicode_ci or a = _utf8mb4'a' collate utf8mb4_0900_ai_ci or a = 'A' or b = 'b' or b = 'b' or b = 'B';
642+
id estRows task access object operator info
643+
TableReader 8006.00 root data:Selection
644+
└─Selection 8006.00 cop[tikv] or(or(eq(planner__core__casetest__predicate_simplification.t3.a, "a"), eq(planner__core__casetest__predicate_simplification.t3.a, "A")), or(eq(planner__core__casetest__predicate_simplification.t3.b, "b"), eq(planner__core__casetest__predicate_simplification.t3.b, "B")))
645+
└─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo
646+
drop table if exists t4;
647+
create table t4(a int, b int, c int, d int, index iab(a,b), index iac(a,c), index iad(a,d));
648+
explain format=brief select /*+ use_index_merge(t4) */ * from t4 where a = 1 and (b = 2 or c = 4 or b = 12 or c = 5 or d = 6 or c = 4 or c = 5 or d = 6);
649+
id estRows task access object operator info
650+
IndexMerge 0.00 root type: union
651+
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t4, index:iab(a, b) range:[1 2,1 2], keep order:false, stats:pseudo
652+
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t4, index:iac(a, c) range:[1 4,1 4], keep order:false, stats:pseudo
653+
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t4, index:iab(a, b) range:[1 12,1 12], keep order:false, stats:pseudo
654+
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t4, index:iac(a, c) range:[1 5,1 5], keep order:false, stats:pseudo
655+
├─IndexRangeScan(Build) 0.10 cop[tikv] table:t4, index:iad(a, d) range:[1 6,1 6], keep order:false, stats:pseudo
656+
└─Selection(Probe) 0.00 cop[tikv] eq(planner__core__casetest__predicate_simplification.t4.a, 1), or(or(eq(planner__core__casetest__predicate_simplification.t4.b, 2), eq(planner__core__casetest__predicate_simplification.t4.c, 4)), or(eq(planner__core__casetest__predicate_simplification.t4.b, 12), or(eq(planner__core__casetest__predicate_simplification.t4.c, 5), eq(planner__core__casetest__predicate_simplification.t4.d, 6))))
657+
└─TableRowIDScan 8.00 cop[tikv] table:t4 keep order:false, stats:pseudo

‎tests/integrationtest/r/planner/core/indexmerge_path.result

+1-2
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ EXPLAIN format = brief SELECT * FROM t WHERE a = 1 AND (c = 13 OR c = 15 OR c =
10121012
id estRows task access object operator info
10131013
IndexLookUp 0.05 root
10141014
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ia(a) range:[1,1], keep order:false, stats:pseudo
1015-
└─Selection(Probe) 0.05 cop[tikv] or(or(eq(planner__core__indexmerge_path.t.c, 13), or(eq(planner__core__indexmerge_path.t.c, 15), eq(planner__core__indexmerge_path.t.c, 5))), or(eq(planner__core__indexmerge_path.t.b, "12"), or(eq(planner__core__indexmerge_path.t.c, 13), eq(planner__core__indexmerge_path.t.b, "11"))))
1015+
└─Selection(Probe) 0.05 cop[tikv] or(or(eq(planner__core__indexmerge_path.t.c, 13), eq(planner__core__indexmerge_path.t.c, 15)), or(eq(planner__core__indexmerge_path.t.c, 5), or(eq(planner__core__indexmerge_path.t.b, "12"), eq(planner__core__indexmerge_path.t.b, "11"))))
10161016
└─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo
10171017
SET @@tidb_opt_fix_control = '52869:on';
10181018
EXPLAIN format = brief SELECT * FROM t WHERE a = 1 AND (b = '2' OR c = 3 OR d = '4');
@@ -1058,7 +1058,6 @@ IndexMerge 0.05 root type: union
10581058
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ic(c) range:[15,15], keep order:false, stats:pseudo
10591059
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ic(c) range:[5,5], keep order:false, stats:pseudo
10601060
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ib(b) range:["12","12"], keep order:false, stats:pseudo
1061-
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ic(c) range:[13,13], keep order:false, stats:pseudo
10621061
├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:ib(b) range:["11","11"], keep order:false, stats:pseudo
10631062
└─Selection(Probe) 0.05 cop[tikv] eq(planner__core__indexmerge_path.t.a, 1)
10641063
└─TableRowIDScan 49.94 cop[tikv] table:t keep order:false, stats:pseudo

‎tests/integrationtest/t/planner/core/casetest/predicate_simplification.test

+27
Original file line numberDiff line numberDiff line change
@@ -282,3 +282,30 @@ SELECT count(*) FROM t1 WHERE (1 = 0 AND a1 = 1) AND (b1 = 2);
282282
SELECT count(*) FROM t1 WHERE (1 = 0 AND a1 = 1) OR (b1 = 2);
283283

284284
# end of test for https://github.com/pingcap/tidb/issues/58171
285+
286+
# Test removing redundant branches from OR list
287+
drop table if exists t1;
288+
create table t1 (a int, b decimal(65,30), c int);
289+
explain format=brief select * from t1 where a = 1 or a = 2 or a = 5 or a = 5 or a = 5;
290+
explain format=brief select * from t1 where a = 1 or a = 2 or a = 5 or a = 5 or a = 5 or b = 1.1 or b = 2.2 or b = 3.3 or b = 3.3;
291+
explain format=brief select * from t1 where a = 1 and (b = 1.1 or b = 2.2 or b = 3.3 or b = 3.3);
292+
explain format=brief select * from t1 where a = 1 or (b = 1.1 and (a = 1 or a = 2 or a = 5 or a = 5 or a = 5));
293+
explain format=brief select * from t1 where (a = 1 and (b = 2.2 or (c = 1 and (b = 1 or b = 1)))) or (b = 1.1 and b = 1.1 and (a = 1 or a = 2 or a = 5 or a = 5 or a = 5));
294+
explain format=brief select * from t1 where (c = 10 or (b + 1 > 10 and (a + 1 < 5 or a + 1 < 5 or a = 20))) and c + 1 < 10 and (a = 1 or a = 2 or a = 5 or a = 5 or b = 5 or b = 5);
295+
explain format=brief select * from t1 where (rand() * 10 = 1) or (rand() * 10 = 1);
296+
explain format=brief select * from t1 where (@a:=@a+1) or (@a:=@a+1);
297+
298+
drop table if exists t2;
299+
create table t2 (a datetime(6), b timestamp(6), index ia(a), index iab(a,b));
300+
explain format=brief select * from t2 where a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00';
301+
explain format=brief select * from t2 where (a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00' or a = '2025-01-01 00:00:00') and (b = '2025-01-01 00:00:00' or b = '2025-01-01 00:00:00' or b = '2025-01-01 00:00:00');
302+
303+
drop table if exists t3;
304+
create table t3 (a varchar(10) collate utf8mb4_general_ci, b varchar(10) collate utf8mb4_bin, index ia(a), index ib(b));
305+
explain format=brief select * from t3 where a = 'a' or a = 'a' or a = 'A';
306+
explain format=brief select * from t3 where a = 'a' or a = 'a' or a = 'A' or b = _utf8mb4'b' or b = _latin1'b' or b = 'B';
307+
explain format=brief select * from t3 where a = _utf8mb4'a' collate utf8mb4_unicode_ci or a = _utf8mb4'a' collate utf8mb4_0900_ai_ci or a = 'A' or b = 'b' or b = 'b' or b = 'B';
308+
309+
drop table if exists t4;
310+
create table t4(a int, b int, c int, d int, index iab(a,b), index iac(a,c), index iad(a,d));
311+
explain format=brief select /*+ use_index_merge(t4) */ * from t4 where a = 1 and (b = 2 or c = 4 or b = 12 or c = 5 or d = 6 or c = 4 or c = 5 or d = 6);

0 commit comments

Comments
 (0)
Please sign in to comment.