This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit cceffcd8dd8209f7a0c736c7aee9bd2ce6847972 Author: Pxl <[email protected]> AuthorDate: Wed Jul 19 01:11:39 2023 +0800 [Bug](materialized view) fix wrong match mv when mv have where clause (#21797) --- .../doris/nereids/jobs/executor/Rewriter.java | 1 + .../mv/AbstractSelectMaterializedIndexRule.java | 55 +++++++--- .../mv/SelectMaterializedIndexWithAggregate.java | 18 ++-- .../SelectMaterializedIndexWithoutAggregate.java | 14 ++- .../org/apache/doris/planner/OlapScanNode.java | 4 +- .../java/org/apache/doris/planner/PlanNode.java | 2 +- .../testAggQueryOnAggMV3/testAggQueryOnAggMV3.out | 2 + .../data/mv_p0/where/k123_nereids/k123_nereids.out | 61 +++++++++++ .../testAggQueryOnAggMV3.groovy | 11 +- .../mv_p0/where/k123_nereids/k123_nereids.groovy | 117 +++++++++++++++++++++ 10 files changed, 244 insertions(+), 41 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java index 06ba235c28..533484331f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java @@ -266,6 +266,7 @@ public class Rewriter extends AbstractBatchJobExecutor { topDown( new SelectMaterializedIndexWithAggregate(), new SelectMaterializedIndexWithoutAggregate(), + new EliminateFilter(), new PushdownFilterThroughProject(), new MergeProjects(), new PruneOlapScanTablet() diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java index bc77b8d058..e91c685fc2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java @@ -20,6 +20,7 @@ package org.apache.doris.nereids.rules.rewrite.mv; import org.apache.doris.analysis.CreateMaterializedViewStmt; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.MaterializedIndex; +import org.apache.doris.catalog.MaterializedIndexMeta; import org.apache.doris.catalog.OlapTable; import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.trees.expressions.Alias; @@ -43,6 +44,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.HllHash; import org.apache.doris.nereids.trees.expressions.functions.scalar.ScalarFunction; import org.apache.doris.nereids.trees.expressions.functions.scalar.ToBitmap; import org.apache.doris.nereids.trees.expressions.functions.scalar.ToBitmapWithCheck; +import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; @@ -55,6 +57,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalRepeat; import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanVisitor; import org.apache.doris.nereids.util.ExpressionUtils; +import org.apache.doris.planner.PlanNode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -90,27 +93,33 @@ public abstract class AbstractSelectMaterializedIndexRule { } } - protected boolean containAllRequiredColumns( - MaterializedIndex index, - LogicalOlapScan scan, - Set<Slot> requiredScanOutput, - Set<? extends Expression> requiredExpr) { - + protected boolean containAllRequiredColumns(MaterializedIndex index, LogicalOlapScan scan, + Set<Slot> requiredScanOutput, Set<? extends Expression> requiredExpr, Set<Expression> predicateExpr) { OlapTable table = scan.getTable(); + MaterializedIndexMeta meta = table.getIndexMetaByIndexId(index.getId()); + + Set<String> predicateExprSql = predicateExpr.stream().map(e -> e.toSql()).collect(Collectors.toSet()); + Set<String> indexConjuncts = PlanNode.splitAndCompoundPredicateToConjuncts(meta.getWhereClause()).stream() + .map(e -> new NereidsParser().parseExpression(e.toSql()).toSql()).collect(Collectors.toSet()); + Set<String> commonConjuncts = indexConjuncts.stream().filter(e -> predicateExprSql.contains(e)) + .collect(Collectors.toSet()); + if (commonConjuncts.size() != indexConjuncts.size()) { + return false; + } Set<String> requiredMvColumnNames = requiredScanOutput.stream() .map(s -> normalizeName(Column.getNameWithoutMvPrefix(s.getName()))) .collect(Collectors.toCollection(() -> new TreeSet<String>(String.CASE_INSENSITIVE_ORDER))); - Set<String> mvColNames = table.getSchemaByIndexId(index.getId(), true).stream() + Set<String> mvColNames = meta.getSchema().stream() .map(c -> normalizeName(parseMvColumnToSql(c.getNameWithoutMvPrefix()))) .collect(Collectors.toCollection(() -> new TreeSet<String>(String.CASE_INSENSITIVE_ORDER))); + mvColNames.addAll(indexConjuncts); return mvColNames.containsAll(requiredMvColumnNames) - || requiredExpr.stream() - .map(AbstractSelectMaterializedIndexRule::removeCastAndAlias) - .filter(e -> !containsAllColumn(e, mvColNames)) - .collect(Collectors.toSet()).isEmpty(); + && (indexConjuncts.isEmpty() || commonConjuncts.size() == predicateExprSql.size()) + || requiredExpr.stream().map(AbstractSelectMaterializedIndexRule::removeCastAndAlias) + .filter(e -> !containsAllColumn(e, mvColNames)).collect(Collectors.toSet()).isEmpty(); } public static String parseMvColumnToSql(String mvName) { @@ -386,7 +395,7 @@ public abstract class AbstractSelectMaterializedIndexRule { Map<Slot, Slot> baseSlotToMvSlot = new HashMap<>(); Map<String, Slot> mvNameToMvSlot = new HashMap<>(); if (mvPlan.getSelectedIndexId() == mvPlan.getTable().getBaseIndexId()) { - return new SlotContext(baseSlotToMvSlot, mvNameToMvSlot); + return new SlotContext(baseSlotToMvSlot, mvNameToMvSlot, new TreeSet<Expression>()); } for (Slot mvSlot : mvPlan.getOutputByIndex(mvPlan.getSelectedIndexId())) { boolean isPushed = false; @@ -411,7 +420,12 @@ public abstract class AbstractSelectMaterializedIndexRule { mvNameToMvSlot.put(normalizeName(mvSlot.getName()), mvSlot); } } - return new SlotContext(baseSlotToMvSlot, mvNameToMvSlot); + OlapTable table = mvPlan.getTable(); + MaterializedIndexMeta meta = table.getIndexMetaByIndexId(mvPlan.getSelectedIndexId()); + + return new SlotContext(baseSlotToMvSlot, mvNameToMvSlot, + PlanNode.splitAndCompoundPredicateToConjuncts(meta.getWhereClause()).stream() + .map(e -> new NereidsParser().parseExpression(e.toSql())).collect(Collectors.toSet())); } /** SlotContext */ @@ -422,9 +436,13 @@ public abstract class AbstractSelectMaterializedIndexRule { // selected mv Slot name to mv Slot, we must use ImmutableSortedMap because column name could be uppercase public final ImmutableSortedMap<String, Slot> mvNameToMvSlot; - public SlotContext(Map<Slot, Slot> baseSlotToMvSlot, Map<String, Slot> mvNameToMvSlot) { + public final ImmutableSet<Expression> trueExprs; + + public SlotContext(Map<Slot, Slot> baseSlotToMvSlot, Map<String, Slot> mvNameToMvSlot, + Set<Expression> trueExprs) { this.baseSlotToMvSlot = ImmutableMap.copyOf(baseSlotToMvSlot); this.mvNameToMvSlot = ImmutableSortedMap.copyOf(mvNameToMvSlot, String.CASE_INSENSITIVE_ORDER); + this.trueExprs = ImmutableSet.copyOf(trueExprs); } } @@ -520,9 +538,12 @@ public abstract class AbstractSelectMaterializedIndexRule { // selected mv Slot name to mv Slot, we must use ImmutableSortedMap because column name could be uppercase private final ImmutableSortedMap<String, Slot> mvNameToMvSlot; + private final ImmutableSet<String> trueExprs; + public ReplaceExpressionWithMvColumn(SlotContext slotContext) { this.baseSlotToMvSlot = ImmutableMap.copyOf(slotContext.baseSlotToMvSlot); this.mvNameToMvSlot = ImmutableSortedMap.copyOf(slotContext.mvNameToMvSlot, String.CASE_INSENSITIVE_ORDER); + this.trueExprs = slotContext.trueExprs.stream().map(e -> e.toSql()).collect(ImmutableSet.toImmutableSet()); } public Expression replace(Expression expression) { @@ -533,9 +554,11 @@ public abstract class AbstractSelectMaterializedIndexRule { public Expression visit(Expression expr, Void context) { if (notUseMv() || org.apache.doris.analysis.CreateMaterializedViewStmt.isMVColumn(expr.toSql())) { return expr; + } else if (trueExprs.contains(expr.toSql())) { + return BooleanLiteral.TRUE; } else if (checkExprIsMvColumn(expr)) { - return mvNameToMvSlot.get( - org.apache.doris.analysis.CreateMaterializedViewStmt.mvColumnBuilder(expr.toSql())); + return mvNameToMvSlot + .get(org.apache.doris.analysis.CreateMaterializedViewStmt.mvColumnBuilder(expr.toSql())); } else { expr = super.visit(expr, context); return expr; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithAggregate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithAggregate.java index 7d0b57d649..062119947b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithAggregate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithAggregate.java @@ -711,12 +711,11 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial List<MaterializedIndex> haveAllRequiredColumns = Streams.concat( candidatesWithoutRewriting.stream() - .filter(index -> containAllRequiredColumns( - index, scan, nonVirtualRequiredScanOutput, requiredExpr)), - candidatesWithRewriting - .stream() + .filter(index -> containAllRequiredColumns(index, scan, nonVirtualRequiredScanOutput, + requiredExpr, predicates)), + candidatesWithRewriting.stream() .filter(aggRewriteResult -> containAllRequiredColumns(aggRewriteResult.index, scan, - aggRewriteResult.requiredScanOutput, requiredExpr)) + aggRewriteResult.requiredScanOutput, requiredExpr, predicates)) .map(aggRewriteResult -> aggRewriteResult.index) ).collect(Collectors.toList()); @@ -757,11 +756,10 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial return baseIndexSelectResult; } else { List<MaterializedIndex> rollupsWithAllRequiredCols = - Stream.concat(candidatesWithoutRewriting.stream(), - indexesGroupByIsBaseOrNot.get(true).stream()) - .filter(index -> containAllRequiredColumns( - index, scan, nonVirtualRequiredScanOutput, requiredExpr)) - .collect(Collectors.toList()); + Stream.concat(candidatesWithoutRewriting.stream(), indexesGroupByIsBaseOrNot.get(true).stream()) + .filter(index -> containAllRequiredColumns(index, scan, nonVirtualRequiredScanOutput, + requiredExpr, predicates)) + .collect(Collectors.toList()); long selectedIndex = selectBestIndex(rollupsWithAllRequiredCols, scan, predicates); if (selectedIndex == scan.getTable().getBaseIndexId()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java index f38a4d3670..9a752db653 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java @@ -183,11 +183,10 @@ public class SelectMaterializedIndexWithoutAggregate extends AbstractSelectMater } if (scan.getTable().isDupKeysOrMergeOnWrite()) { // Set pre-aggregation to `on` to keep consistency with legacy logic. - List<MaterializedIndex> candidates = scan.getTable().getVisibleIndex().stream() - .filter(index -> index.getId() != baseIndexId) - .filter(index -> !indexHasAggregate(index, scan)) - .filter(index -> containAllRequiredColumns(index, scan, - requiredScanOutputSupplier.get(), requiredExpr)) + List<MaterializedIndex> candidates = scan + .getTable().getVisibleIndex().stream().filter(index -> index.getId() != baseIndexId) + .filter(index -> !indexHasAggregate(index, scan)).filter(index -> containAllRequiredColumns(index, + scan, requiredScanOutputSupplier.get(), requiredExpr, predicatesSupplier.get())) .collect(Collectors.toList()); long bestIndex = selectBestIndex(candidates, scan, predicatesSupplier.get()); return scan.withMaterializedIndexSelected(PreAggStatus.on(), bestIndex); @@ -207,9 +206,8 @@ public class SelectMaterializedIndexWithoutAggregate extends AbstractSelectMater // So only base index and indexes that have all the keys could be used. List<MaterializedIndex> candidates = table.getVisibleIndex().stream() .filter(index -> table.getKeyColumnsByIndexId(index.getId()).size() == baseIndexKeySize) - .filter(index -> containAllRequiredColumns( - index, scan, requiredScanOutputSupplier.get(), - predicatesSupplier.get())) + .filter(index -> containAllRequiredColumns(index, scan, requiredScanOutputSupplier.get(), + requiredExpr, predicatesSupplier.get())) .collect(Collectors.toList()); if (candidates.size() == 1) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java index 1fcac274ec..6f10836a90 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java @@ -100,7 +100,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -359,8 +358,7 @@ public class OlapScanNode extends ScanNode { return; } Expr vconjunct = convertConjunctsToAndCompoundPredicate(conjuncts).replaceSubPredicate(whereExpr); - conjuncts = splitAndCompoundPredicateToConjuncts(vconjunct).stream().filter(Objects::nonNull) - .collect(Collectors.toList()); + conjuncts = splitAndCompoundPredicateToConjuncts(vconjunct).stream().collect(Collectors.toList()); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java index 6a2d9c0f8b..a279af676e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java @@ -439,7 +439,7 @@ public abstract class PlanNode extends TreeNode<PlanNode> implements PlanStats { conjuncts.addAll(splitAndCompoundPredicateToConjuncts(vconjunct.getChild(1))); } } - if (conjuncts.isEmpty()) { + if (vconjunct != null && conjuncts.isEmpty()) { conjuncts.add(vconjunct); } return conjuncts; diff --git a/regression-test/data/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.out b/regression-test/data/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.out index 279e3ee410..0ae3aec19b 100644 --- a/regression-test/data/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.out +++ b/regression-test/data/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.out @@ -8,3 +8,5 @@ -- !select_mv -- 4 4 +-- !select_mv -- + diff --git a/regression-test/data/mv_p0/where/k123_nereids/k123_nereids.out b/regression-test/data/mv_p0/where/k123_nereids/k123_nereids.out new file mode 100644 index 0000000000..d5dc7d3c21 --- /dev/null +++ b/regression-test/data/mv_p0/where/k123_nereids/k123_nereids.out @@ -0,0 +1,61 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select_star -- +1 1 1 a +1 1 1 a +2 2 2 b +2 2 2 b +3 -3 \N c +3 -3 \N c + +-- !select_mv -- +1 2 +1 2 +2 4 +2 4 +3 \N +3 \N + +-- !select_mv -- +1 2 +1 2 + +-- !select_mv -- +2 4 +2 4 + +-- !select_mv -- +1 2 +1 2 + +-- !select_mv -- +2 4 +2 4 + +-- !select_mv -- +1 2 +1 2 + +-- !select_mv -- +2 4 +2 4 + +-- !select_mv_constant -- +\N +\N +\N +\N +\N +\N + +-- !select_mv -- + +-- !select_mv -- + +-- !select_mv -- +1 true +1 true + +-- !select_mv -- +1 false +1 false + diff --git a/regression-test/suites/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.groovy b/regression-test/suites/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.groovy index 5d881724e0..cb66c8a461 100644 --- a/regression-test/suites/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.groovy +++ b/regression-test/suites/mv_p0/ut/testAggQueryOnAggMV3/testAggQueryOnAggMV3.groovy @@ -39,7 +39,7 @@ suite ("testAggQueryOnAggMV3") { - createMV("create materialized view emps_mv as select deptno, commission, sum(salary) from emps group by deptno, commission ;") + createMV("create materialized view emps_mv as select deptno, commission, sum(salary) from emps group by deptno, commission;") explain { @@ -49,10 +49,15 @@ suite ("testAggQueryOnAggMV3") { qt_select_star "select * from emps order by empid;" - explain { + explain { sql("select commission, sum(salary) from emps where commission * (deptno + commission) = 100 group by commission order by commission;") contains "(emps_mv)" } qt_select_mv "select commission, sum(salary) from emps where commission * (deptno + commission) = 100 group by commission order by commission;" -} \ No newline at end of file + explain { + sql("select commission, sum(salary) from emps where commission = 100 group by commission order by commission;") + contains "(emps_mv)" + } + qt_select_mv "select commission, sum(salary) from emps where commission = 100 group by commission order by commission;" +} diff --git a/regression-test/suites/mv_p0/where/k123_nereids/k123_nereids.groovy b/regression-test/suites/mv_p0/where/k123_nereids/k123_nereids.groovy new file mode 100644 index 0000000000..e034beaf11 --- /dev/null +++ b/regression-test/suites/mv_p0/where/k123_nereids/k123_nereids.groovy @@ -0,0 +1,117 @@ +// 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. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite ("k123p_nereids") { + sql """ DROP TABLE IF EXISTS d_table; """ + sql """set enable_nereids_planner=true""" + sql """ + create table d_table( + k1 int null, + k2 int not null, + k3 bigint null, + k4 varchar(100) null + ) + duplicate key (k1,k2,k3) + distributed BY hash(k1) buckets 3 + properties("replication_num" = "1"); + """ + + sql "insert into d_table select 1,1,1,'a';" + sql "insert into d_table select 2,2,2,'b';" + sql "insert into d_table select 3,-3,null,'c';" + + createMV ("""create materialized view k123p1w as select k1,k2+k3 from d_table where k1 = 1;""") + createMV ("""create materialized view k123p4w as select k1,k2+k3 from d_table where k4 = "b";""") + createMV ("""create materialized view kwh1 as select k2 from d_table where k1=1;""") + + + sql "insert into d_table select 1,1,1,'a';" + sql "insert into d_table select 2,2,2,'b';" + sql "insert into d_table select 3,-3,null,'c';" + + qt_select_star "select * from d_table order by k1;" + + explain { + sql("select k1,k2+k3 from d_table order by k1;") + contains "(d_table)" + } + qt_select_mv "select k1,k2+k3 from d_table order by k1;" + + explain { + sql("select k1,k2+k3 from d_table where k1 = 1 order by k1;") + contains "(k123p1w)" + } + qt_select_mv "select k1,k2+k3 from d_table where k1 = 1 order by k1;" + + explain { + sql("select k1,k2+k3 from d_table where k1 = 2 order by k1;") + contains "(d_table)" + } + qt_select_mv "select k1,k2+k3 from d_table where k1 = 2 order by k1;" + + explain { + sql("select k1,k2+k3 from d_table where k1 = '1' order by k1;") + contains "(k123p1w)" + } + qt_select_mv "select k1,k2+k3 from d_table where k1 = '1' order by k1;" + + explain { + sql("select k1,k2+k3 from d_table where k4 = 'b' order by k1;") + contains "(k123p4w)" + } + qt_select_mv "select k1,k2+k3 from d_table where k4 = 'b' order by k1;" + + explain { + sql("select k1,k2+k3 from d_table where k4 = 'a' order by k1;") + contains "(d_table)" + } + qt_select_mv "select k1,k2+k3 from d_table where k4 = 'a' order by k1;" + + explain { + sql("""select k1,k2+k3 from d_table where k1 = 2 and k4 = "b";""") + contains "(k123p4w)" + } + qt_select_mv """select k1,k2+k3 from d_table where k1 = 2 and k4 = "b" order by k1;""" + + qt_select_mv_constant """select bitmap_empty() from d_table where true;""" + + explain { + sql("select k2 from d_table where k1=1 and (k1>2 or k1 < 0) order by k2;") + contains "(d_table)" + } + qt_select_mv "select k2 from d_table where k1=1 and (k1>2 or k1 < 0) order by k2;" + + explain { + sql("select k2 from d_table where k1=1 and (k2>2 or k2<0) order by k2;") + contains "(kwh1)" + } + qt_select_mv "select k2 from d_table where k1=1 and (k2>2 or k2<0) order by k2;" + + explain { + sql("select k2,k1=1 from d_table where k1=1 order by k2;") + contains "(kwh1)" + } + qt_select_mv "select k2,k1=1 from d_table where k1=1 order by k2;" + + explain { + sql("select k2,k1=2 from d_table where k1=1 order by k2;") + contains "(d_table)" + } + qt_select_mv "select k2,k1=2 from d_table where k1=1 order by k2;" +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
