diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java index d63f2bad43d742..2d6c3867d2dbb3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java @@ -253,13 +253,35 @@ private ValueDesc processCompound(ExpressionRewriteContext context, List resultValues = Lists.newArrayList(); + if (collector.hasIsNullValue) { + if (!collector.rangeValues.isEmpty() + || !collector.discreteValues.isEmpty() + || !collector.notDiscreteValues.isEmpty()) { + // TA is null and TA > 1 + // => TA is null and (null) + // => TA is null and null + // => EmptyValue(TA) + collector.rangeValues.clear(); + collector.discreteValues.clear(); + collector.notDiscreteValues.clear(); + collector.add(new EmptyValue(context, reference)); + } + } + List resultValues = Lists.newArrayList(); // merge all the range values Range mergeRangeValue = null; if (!collector.hasEmptyValue && !collector.rangeValues.isEmpty()) { RangeValue mergeRangeValueDesc = null; for (RangeValue rangeValue : collector.rangeValues) { + // RangeAll(TA) and IsNotNull(TA) + // = (TA is not null or null) and (TA is not null) + // = TA is not null + // = IsNotNull(TA) + if (rangeValue.isRangeAll() && collector.hasIsNotNullValue()) { + // skip this RangeAll + continue; + } if (mergeRangeValueDesc == null) { mergeRangeValueDesc = rangeValue; } else { @@ -337,24 +359,22 @@ private ValueDesc intersect(ExpressionRewriteContext context, Expression referen } resultValues.add(new EmptyValue(context, reference)); } - - // RangeAll = (a is not null or null), only a is not nullable, then RangeAll equals IsNotNull - // process is null and is not null - // for non-nullable a: EmptyValue(a) = a is null and null - boolean hasIsNullValue = collector.hasIsNullValue || collector.hasEmptyValue && reference.nullable(); - boolean hasIsNotNullValue = collector.isNotNullValueOpt.isPresent() - || collector.isGenerateNotNullValueOpt.isPresent() - || (!reference.nullable() && mergeRangeValue != null - && !mergeRangeValue.hasLowerBound() && !mergeRangeValue.hasUpperBound()); - if (hasIsNullValue && hasIsNotNullValue) { - return new UnknownValue(context, BooleanLiteral.FALSE); + if (collector.hasIsNullValue) { + if (collector.hasIsNotNullValue()) { + return new UnknownValue(context, BooleanLiteral.FALSE); + } + // nullable's EmptyValue have contains IsNull, no need to add + if (!collector.hasEmptyValue) { + resultValues.add(new IsNullValue(context, reference)); + } } - // nullable's EmptyValue have contains IsNull, no need to add - if (!collector.hasEmptyValue && collector.hasIsNullValue) { - resultValues.add(new IsNullValue(context, reference)); + if (collector.hasIsNotNullValue()) { + if (collector.hasEmptyValue) { + return new UnknownValue(context, BooleanLiteral.FALSE); + } + collector.isNotNullValueOpt.ifPresent(resultValues::add); + collector.isGenerateNotNullValueOpt.ifPresent(resultValues::add); } - collector.isNotNullValueOpt.ifPresent(resultValues::add); - collector.isGenerateNotNullValueOpt.ifPresent(resultValues::add); Optional shortCutResult = mergeCompoundValues(context, reference, resultValues, collector, true); if (shortCutResult.isPresent()) { return shortCutResult.get(); @@ -371,6 +391,21 @@ private ValueDesc intersect(ExpressionRewriteContext context, Expression referen } private ValueDesc union(ExpressionRewriteContext context, Expression reference, ValueDescCollector collector) { + if (collector.hasIsNotNullValue()) { + if (!collector.rangeValues.isEmpty() + || !collector.discreteValues.isEmpty() + || !collector.notDiscreteValues.isEmpty()) { + // TA is not null or TA > 1 + // => TA is not null or (null) + // => TA is not null or null + // => RangeAll(TA) + collector.rangeValues.clear(); + collector.discreteValues.clear(); + collector.notDiscreteValues.clear(); + collector.add(new RangeValue(context, reference, Range.all())); + } + } + List resultValues = Lists.newArrayListWithExpectedSize(collector.size() + 3); // Since in-predicate's options is a list, the discrete values need to kept options' order. // If not keep options' order, the result in-predicate's option list will not equals to @@ -429,17 +464,25 @@ private ValueDesc union(ExpressionRewriteContext context, Expression reference, } } - boolean hasIsNullValue = collector.hasIsNullValue || collector.hasEmptyValue && !reference.nullable(); - boolean hasIsNotNullValue = collector.isNotNullValueOpt.isPresent() - || collector.isGenerateNotNullValueOpt.isPresent() || hasRangeAll; - if (hasIsNullValue && hasIsNotNullValue) { - return new UnknownValue(context, BooleanLiteral.TRUE); - } else if (collector.hasIsNullValue) { + if (collector.hasIsNullValue) { + if (collector.hasIsNotNullValue() || hasRangeAll) { + return new UnknownValue(context, BooleanLiteral.TRUE); + } resultValues.add(new IsNullValue(context, reference)); - } else { - collector.isNotNullValueOpt.ifPresent(resultValues::add); - collector.isGenerateNotNullValueOpt.ifPresent(resultValues::add); } + if (collector.hasIsNotNullValue()) { + if (collector.hasEmptyValue) { + // EmptyValue(TA) or TA is not null + // = TA is null and null or TA is not null + // = TA is not null or null + // = RangeAll(TA) + resultValues.add(new RangeValue(context, reference, Range.all())); + } else { + collector.isNotNullValueOpt.ifPresent(resultValues::add); + collector.isGenerateNotNullValueOpt.ifPresent(resultValues::add); + } + } + Optional shortCutResult = mergeCompoundValues(context, reference, resultValues, collector, false); if (shortCutResult.isPresent()) { return shortCutResult.get(); @@ -483,7 +526,6 @@ private Optional mergeCompoundValues(ExpressionRewriteContext context ImmutableList.Builder newSourceValuesBuilder = ImmutableList.builderWithExpectedSize(compoundValue.sourceValues.size()); boolean skipWholeCompoundValue = false; - boolean hasNullableSkipSourceValues = false; for (ValueDesc innerValue : compoundValue.sourceValues) { IntersectType intersectType = IntersectType.OTHERS; UnionType unionType = UnionType.OTHERS; @@ -491,18 +533,17 @@ private Optional mergeCompoundValues(ExpressionRewriteContext context if (isAnd) { skipWholeCompoundValue = skipWholeCompoundValue || innerValue.containsAll(outerValue); IntersectType type = outerValue.getIntersectType(innerValue); - if (type == IntersectType.EMPTY_VALUE - && intersectType != IntersectType.FALSE - && outerValue.nullable()) { + if (type == IntersectType.EMPTY_VALUE && intersectType != IntersectType.FALSE) { intersectType = type; - } - if (type == IntersectType.FALSE) { + } else if (type == IntersectType.FALSE) { intersectType = type; } } else { skipWholeCompoundValue = skipWholeCompoundValue || outerValue.containsAll(innerValue); UnionType type = outerValue.getUnionType(innerValue); - if (type == UnionType.TRUE) { + if (type == UnionType.RANGE_ALL && unionType != UnionType.TRUE) { + unionType = type; + } else if (type == UnionType.TRUE) { unionType = type; } } @@ -513,33 +554,27 @@ private Optional mergeCompoundValues(ExpressionRewriteContext context if (isAnd) { if (intersectType == IntersectType.OTHERS) { newSourceValuesBuilder.add(innerValue); - } else { - hasNullableSkipSourceValues = hasNullableSkipSourceValues - || intersectType == IntersectType.EMPTY_VALUE; + } else if (intersectType == IntersectType.EMPTY_VALUE) { + newSourceValuesBuilder.add(new EmptyValue(context, reference)); } } else { if (unionType == UnionType.OTHERS) { newSourceValuesBuilder.add(innerValue); - } else { - hasNullableSkipSourceValues = hasNullableSkipSourceValues - || unionType == UnionType.RANGE_ALL; + } else if (unionType == UnionType.RANGE_ALL) { + newSourceValuesBuilder.add(new RangeValue(context, reference, Range.all())); } } } if (!skipWholeCompoundValue) { List newSourceValues = newSourceValuesBuilder.build(); if (newSourceValues.isEmpty()) { - if (isAnd) { - if (!hasNullableSkipSourceValues) { - return Optional.of(new UnknownValue(context, BooleanLiteral.FALSE)); - } - resultValues.add(new EmptyValue(context, reference)); - } else { - if (!hasNullableSkipSourceValues) { - return Optional.of(new UnknownValue(context, BooleanLiteral.TRUE)); - } - resultValues.add(new RangeValue(context, reference, Range.all())); - } + // when isAnd = true, A and (B or C or D) + // if A and B = FALSE, A and C = FALSE, A and D = FALSE, then newSourceValues is empty + // then A and (B or C or D) = FALSE + // when isAnd = false, A or (B and C and D) + // if A or B = TRUE, A or C = TRUE, A or D = TRUE, then newSourceValues is empty + // then A or (B and C and D) = TRUE + return Optional.of(new UnknownValue(context, BooleanLiteral.of(!isAnd))); } else if (newSourceValues.size() == 1) { resultValues.add(newSourceValues.get(0)); } else { @@ -594,6 +629,10 @@ int size() { return rangeValues.size() + discreteValues.size() + compoundValues.size() + unknownValues.size(); } + boolean hasIsNotNullValue() { + return isNotNullValueOpt.isPresent() || isGenerateNotNullValueOpt.isPresent(); + } + @Override public Void visitEmptyValue(EmptyValue emptyValue, Void context) { hasEmptyValue = true; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java index 0f8a1d60fe814b..c5f89259a363f1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java @@ -72,7 +72,7 @@ * 1. a > 1 => RangeValueDesc((1...+∞)), a > 2 => RangeValueDesc((2...+∞)) * 2. (1...+∞) intersect (2...+∞) => (2...+∞) * 2. for `Or` expression (similar to `And`). - * todo: support a > 10 and (a < 10 or a > 20 ) => a > 20 + * 3. a > 10 and (a < 10 or a > 20 ) => a > 20 */ public class SimplifyRange implements ExpressionPatternRuleFactory, ValueDescVisitor { public static final SimplifyRange INSTANCE = new SimplifyRange(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java index 3d9341d2b0cbb7..117f01146bf116 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/SimplifyRangeTest.java @@ -189,7 +189,7 @@ public void testValueDescContainsAll() { checkContainsAll(false, "TA is null", "TA != 10"); checkContainsAll(true, "TA is null", "TA is null"); checkContainsAll(false, "TA is null", "TA is not null"); - checkContainsAll(true, "TA is null", "TA is null and (TA > 10)"); + checkContainsAll(false, "TA is null", "TA is null and (TA > 10)"); checkContainsAll(false, "TA is null", "TA is null or (TA > 10)"); checkContainsAll(false, "TA is not null", "TA is null and null"); @@ -293,8 +293,8 @@ public void testSimplifyNumeric() { assertRewrite("TA is null", "TA is null"); assertRewrite("TA is null and null or TA = 1", "TA = 1"); assertRewrite("TA is null and null or TA is null", "TA is null"); - assertRewrite("TA is null and null or (TA is null and TA > 10) ", "(TA > 10 and TA is null) or TA is null and null"); - assertRewrite("TA is null and null or TA is not null", "TA is not null or TA is null and null"); + assertRewrite("TA is null and null or (TA is null and TA > 10) ", "TA is null and null"); + assertRewrite("TA is null and null or TA is not null", "TA is not null or null"); assertRewriteNotNull("TA != 1 or TA != 2", "TRUE"); assertRewrite("TA is null or TA is not null", "TRUE"); assertRewrite("TA > 5 and TA > 1 and TA > 10", "TA > 10"); @@ -320,7 +320,7 @@ public void testSimplifyNumeric() { assertRewrite("TA in (1,2,3) and TA >= 1", "TA in (1,2,3)"); assertRewrite("TA in (1,2,3) and TA > 1", "TA IN (2, 3)"); assertRewrite("TA in (1,2,3) or TA >= 1", "TA >= 1"); - assertRewrite("TA is null and (TA = 4 or TA = 5)", "TA in (4, 5) and TA is null"); + assertRewrite("TA is null and (TA = 4 or TA = 5)", "TA is null and null"); assertRewrite("(TA != 3 or TA is null) and (TA = 4 or TA = 5)", "TA in (4, 5)"); assertRewrite("TA in (1)", "TA in (1)"); assertRewrite("TA in (1,2,3) and TA < 10", "TA in (1,2,3)"); @@ -347,7 +347,21 @@ public void testSimplifyNumeric() { assertRewrite("TA > 3 and TB < 5 and TA < 1", "TA is null and null and TB < 5"); assertRewrite("(TA > 3 and TA < 1) or TB < 5", "(TA is null and null) or TB < 5"); + assertRewrite("TA is null and TA > 10", "TA is null and null"); + assertRewrite("TA is null and TA = 10", "TA is null and null"); + assertRewrite("TA is null and TA != 10", "TA is null and null"); + assertRewriteNotNull("TA is null and TA > 10", "FALSE"); + assertRewriteNotNull("TA is null and TA = 10", "FALSE"); + assertRewriteNotNull("TA is null and TA != 10", "FALSE"); + assertRewrite("TA is not null or TA > 10", "TA is not null or null"); + assertRewrite("TA is not null or TA = 10", "TA is not null or null"); + assertRewrite("TA is not null or TA != 10", "TA is not null or null"); + assertRewriteNotNull("TA is not null or TA > 10", "TRUE"); + assertRewriteNotNull("TA is not null or TA = 10", "TRUE"); + assertRewriteNotNull("TA is not null or TA != 10", "TRUE"); + // A and (B or C) = A + assertRewrite("TA < 10 and (TA is not null or TA is null and null)", "TA < 10"); assertRewrite("TA > 10 and (TA > 5 or (TA is not null and TA > 1))", "TA > 10"); assertRewrite("TA > 10 and (TA != 4 or (TA is not null and TA > 1))", "TA > 10"); assertRewrite("TA = 5 and (TA != 4 or (TA is not null and TA > 1))", "TA = 5"); @@ -355,7 +369,8 @@ public void testSimplifyNumeric() { assertRewrite("TA = 5 and (TA > 3 or (TA is not null and TA > 1))", "TA = 5"); assertRewrite("TA not in (1, 2) and (TA not in (1) or (TA is not null and TA > 1))", "TA not in (1, 2)"); assertRewrite("TA not in (1, 2) and (TA not in (1, 2) or (TA is not null and TA > 1))", "TA not in (1, 2)"); - assertRewrite("TA not in (1, 2) and (TA not in (2, 3) or (TA is not null and TA > 1))", "TA not in (1, 2) and (TA not in (2, 3) or (TA > 1 and TA is not null))"); + assertRewrite("TA not in (2, 3) or (TA is not null and TA > 1)", "TA is not null or null"); + assertRewrite("TA not in (1, 2) and (TA not in (2, 3) or (TA is not null and TA > 1))", "TA not in (1, 2)"); assertRewrite("TA is null and null and (TA = 10 or (TA is not null and TA > 1))", "TA is null and null"); assertRewrite("TA is null and null and (TA != 10 or (TA is not null and TA > 1))", "TA is null and null"); assertRewrite("TA is null and null and (TA > 20 or (TA is not null and TA > 1))", "TA is null and null"); @@ -372,7 +387,7 @@ public void testSimplifyNumeric() { assertRewriteNotNull("TA is not null", "TA is not null"); assertRewrite("TA is null and null or TA is null", "TA is null"); assertRewriteNotNull("TA is null and null or TA is null", "TA is null"); - assertRewrite("TA is null and null or TA is not null", "TA is not null or TA is null and null"); + assertRewrite("TA is null and null or TA is not null", "TA is not null or null"); assertRewriteNotNull("TA is null and null or TA is not null", "not TA is null"); assertRewrite("TA is null or TA is not null", "TRUE"); assertRewriteNotNull("TA is null or TA is not null", "TRUE"); @@ -393,18 +408,17 @@ public void testSimplifyNumeric() { assertRewrite("(TA is null or null) or TA is null", "TA is null or null"); assertRewrite("(TA is not null and null) and TA is null", "FALSE"); assertRewrite("(TA is not null and null) or TA is null", "TA is not null and null or TA is null"); - // can simplify to 'TA is null and null', but not supported yet, because it treat 'TA is not null or null' to RangeAll - assertRewrite("(TA is not null or null) and TA is null", "(TA is not null or null) and TA is null"); + assertRewrite("(TA is not null or null) and TA is null", "TA is null and null"); assertRewrite("(TA is not null or null) or TA is null", "TRUE"); assertRewrite("(TA is null and null) and TA is not null", "FALSE"); - assertRewrite("(TA is null and null) or TA is not null", "TA is not null or TA is null and null"); + assertRewrite("(TA is null and null) or TA is not null", "TA is not null or null"); assertRewrite("(TA is null or null) and TA is not null", "(TA is null or null) and TA is not null"); assertRewrite("(TA is null or null) or TA is not null", "TRUE"); assertRewrite("(TA is not null and null) and TA is not null", "TA is not null and null"); // can simplify to 'TA is not null', but not supported yet assertRewrite("(TA is not null and null) or TA is not null", "TA is not null and null or TA is not null"); // can simplify to 'TA is not null', but not supported yet - assertRewrite("(TA is not null or null) and TA is not null", "(TA is not null or null) and TA is not null"); + assertRewrite("(TA is not null or null) and TA is not null", "TA is not null"); assertRewrite("(TA is not null or null) or TA is not null", "TA is not null or null"); assertRewrite("(XA is null and null) and XA is null", "FALSE"); @@ -433,6 +447,26 @@ public void testSimplifyNumeric() { assertRewrite("(XA is not null or null) and XA is not null", "XA is not null"); assertRewrite("(XA is not null or null) or XA is not null", "TRUE"); + assertRewrite("TA is not null or TA is null and null", "TA is not null or null"); + assertRewrite("TA > 100 and (TA < 10 or TA between 15 and 20)", "TA is null and null"); + assertRewrite("TA > 100 and (TA < 10 or TA between 15 and 20 or TA between 110 and 115)", "TA between 110 and 115"); + assertRewrite("TA > 100 and (TA < 10 or TA between 15 and 20 or TA is null)", "TA is null and null"); + assertRewrite("TA > 100 and (TA < 10 or TA between 15 and 20 or TA is not null)", "TA > 100"); + assertRewriteNotNull("TA is not null or TA is null and null", "TA is not null"); + assertRewriteNotNull("TA > 100 and (TA < 10 or TA between 15 and 20)", "FALSE"); + assertRewriteNotNull("TA > 100 and (TA < 10 or TA between 15 and 20 or TA is null)", "FALSE"); + assertRewriteNotNull("TA > 100 and (TA < 10 or TA between 15 and 20 or TA is not null)", "TA > 100"); + assertRewrite("TA > 100 or (TA < 120 and TA is null)", "TA > 100"); + assertRewrite("TA > 100 or (TA < 120 and TA is not null)", "TA is not null or null"); + assertRewrite("TA > 100 or (TA < 120 and TA != 80)", + "TA > 100 or ((TA is not null or null) and TA != 80)"); + assertRewrite("TA > 100 or (TA < 120 and TA != 110)", "TA is not null or null"); + assertRewriteNotNull("TA > 100 or (TA < 120 and TA is null)", "TA > 100"); + assertRewriteNotNull("TA > 100 or (TA < 120 and TA is not null)", "TRUE"); + assertRewriteNotNull("TA > 100 or (TA < 120 and TA != 80)", + "TA != 80"); + assertRewriteNotNull("TA > 100 or (TA < 120 and TA != 110)", "TRUE"); + assertRewrite("TA + TC", "TA + TC"); assertRewrite("(TA + TC >= 1 and TA + TC <=3 ) or (TA + TC > 5 and TA + TC < 7)", "(TA + TC >= 1 and TA + TC <=3 ) or (TA + TC > 5 and TA + TC < 7)"); assertRewriteNotNull("(TA + TC > 3 and TA + TC < 1) or (TA + TC > 7 and TA + TC < 5)", "FALSE"); diff --git a/regression-test/data/nereids_rules_p0/case_when_rules/test_case_when_rules.out b/regression-test/data/nereids_rules_p0/case_when_rules/test_case_when_rules.out new file mode 100644 index 00000000000000..686bcfd06f13bd --- /dev/null +++ b/regression-test/data/nereids_rules_p0/case_when_rules/test_case_when_rules.out @@ -0,0 +1,56 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql_1_shape -- +PhysicalResultSink +--PhysicalProject +----filter(a IN (1, 3)) +------PhysicalOlapScan[tbl_test_case_when_rules] + +-- !sql_1_result -- +1 10 101 +3 30 103 + +-- !sql_2_shape -- +PhysicalResultSink +--PhysicalProject +----filter((tbl_test_case_when_rules.a = 4)) +------PhysicalOlapScan[tbl_test_case_when_rules] + +-- !sql_2_result -- +4 40 104 + +-- !sql_3_shape -- +PhysicalResultSink +--PhysicalProject +----filter(OR[( not a IN (1, 2, 3)),a IS NULL]) +------PhysicalOlapScan[tbl_test_case_when_rules] + +-- !sql_3_result -- +\N 0 107 +4 40 104 +5 50 107 +6 60 107 + +-- !sql_4_shape -- +PhysicalResultSink +--PhysicalProject +----filter(OR[( not (a = 3)),a IS NULL]) +------PhysicalOlapScan[tbl_test_case_when_rules] + +-- !sql_4_result -- +\N 0 107 +1 10 101 +2 20 102 +4 40 104 +5 50 107 +6 60 107 + +-- !sql_5_shape -- +PhysicalResultSink +--PhysicalProject +----filter(a IN (1, 2)) +------PhysicalOlapScan[tbl_test_case_when_rules] + +-- !sql_5_result -- +1 10 101 +2 20 102 + diff --git a/regression-test/data/nereids_rules_p0/filter_push_down/push_down_filter_other_condition.out b/regression-test/data/nereids_rules_p0/filter_push_down/push_down_filter_other_condition.out index 359c8aace759a5..51c751b763006c 100644 --- a/regression-test/data/nereids_rules_p0/filter_push_down/push_down_filter_other_condition.out +++ b/regression-test/data/nereids_rules_p0/filter_push_down/push_down_filter_other_condition.out @@ -229,7 +229,7 @@ PhysicalResultSink -- !pushdown_left_outer_join_subquery_outer -- PhysicalResultSink ---NestedLoopJoin[INNER_JOIN]OR[(t1.id = t2.id),AND[(id > 1),id IS NULL]] +--hashJoin[INNER_JOIN] hashCondition=((t1.id = t2.id)) otherCondition=() ----PhysicalOlapScan[t1] ----PhysicalAssertNumRows ------PhysicalOlapScan[t2] diff --git a/regression-test/suites/nereids_rules_p0/case_when_rules/test_case_when_rules.groovy b/regression-test/suites/nereids_rules_p0/case_when_rules/test_case_when_rules.groovy new file mode 100644 index 00000000000000..41ec4302eec090 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/case_when_rules/test_case_when_rules.groovy @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +suite("test_case_when_rules") { + + // this test will invoke many rules, including: + // PUSH_INTO_CASE_WHEN_BRNACH + // CASE_WHEN_TO_COMPOUND_PREDICATE + // NULL_SAFE_EQUAL_TO_EQUAL + // SIMPLIFY_RANGE + + sql """ + SET ignore_shape_nodes='PhysicalDistribute'; + SET runtime_filter_mode=OFF; + SET disable_join_reorder=true; + drop table if exists tbl_test_case_when_rules force; + create table tbl_test_case_when_rules(a bigint, b bigint) properties('replication_num' = '1'); + insert into tbl_test_case_when_rules values(null, 0), (1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60) + """ + + explainAndOrderResult 'sql_1', ''' + select * + from ( + select a, b, case when a = 1 then 101 when a = 2 then 102 when a = 3 then 103 when a = 4 then 104 end as k + from tbl_test_case_when_rules + ) s + where k = 101 or k = 103 or k = 105 + ''' + + explainAndOrderResult 'sql_2', ''' + select * + from ( + select a, b, case when a = 1 then 101 when a = 2 then 102 when a = 3 then 103 when a = 4 then 104 end as k + from tbl_test_case_when_rules + ) s + where k > 103 + ''' + + explainAndOrderResult 'sql_3', ''' + select * + from ( + select a, b, case when a = 1 then 101 when a = 2 then 102 when a = 3 then 103 when a = 4 then 104 else 107 end as k + from tbl_test_case_when_rules + ) s + where k > 103 + ''' + + explainAndOrderResult 'sql_4', ''' + select * + from ( + select a, b, case when a = 1 then 101 when a = 2 then 102 when a = 3 then 103 when a = 4 then 104 else 107 end as k + from tbl_test_case_when_rules + ) s + where k != 103 + ''' + + explainAndOrderResult 'sql_5', ''' + select * + from ( + select a, b, case when a = 1 then 101 when a = 2 then 102 when a = 3 then 103 when a = 4 then 104 else 107 end as k + from tbl_test_case_when_rules + ) s + where k < 103 + ''' +}