This is an automated email from the ASF dual-hosted git repository. mblow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 37d339e25636de8eaa5ad7f21bbf18c3873219b4 Author: Dmitry Lychagin <[email protected]> AuthorDate: Mon Aug 17 17:20:53 2020 -0700 [NO ISSUE][COMP] Support skip-index for IN operator Details: - Support skip-index hint for IN operator: WHERE indexed_field /*+ skip-index */ IN [...] Change-Id: Ib76f43b53c2bc1b0f5c12e03f555a8d2c1d75701 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/7603 Integration-Tests: Jenkins <[email protected]> Tested-by: Dmitry Lychagin <[email protected]> Reviewed-by: Dmitry Lychagin <[email protected]> Reviewed-by: Ali Alsuliman <[email protected]> --- .../rules/DisjunctivePredicateToJoinRule.java | 24 ++++++++++-- .../SqlppExpressionToPlanTranslator.java | 26 ++++++++----- .../skip-index/skip-secondary-btree-index-3.sqlpp | 43 ++++++++++++++++++++++ .../skip-index/skip-secondary-btree-index-3.plan | 15 ++++++++ .../visitor/OperatorExpressionVisitor.java | 1 + 5 files changed, 96 insertions(+), 13 deletions(-) diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java index 916fd75..fe03d75 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/DisjunctivePredicateToJoinRule.java @@ -18,9 +18,13 @@ */ package org.apache.asterix.optimizer.rules; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation; import org.apache.asterix.metadata.declared.MetadataProvider; import org.apache.asterix.om.base.AOrderedList; import org.apache.asterix.om.constants.AsterixConstantValue; @@ -39,6 +43,7 @@ import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable; import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation; import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression; +import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation; import org.apache.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation; import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression; @@ -89,6 +94,7 @@ public class DisjunctivePredicateToJoinRule implements IAlgebraicRewriteRule { VariableReferenceExpression varEx = null; IAType valType = null; HashSet<AsterixConstantValue> values = new HashSet<AsterixConstantValue>(); + Map<Object, IExpressionAnnotation> allAnnotations = Collections.emptyMap(); for (Mutable<ILogicalExpression> arg : args) { AbstractFunctionCallExpression fctCall; @@ -128,6 +134,12 @@ public class DisjunctivePredicateToJoinRule implements IAlgebraicRewriteRule { if (!(haveVar && haveConst)) { return false; } + if (!fctCall.getAnnotations().isEmpty()) { + if (allAnnotations.isEmpty()) { + allAnnotations = new HashMap<>(); + } + allAnnotations.putAll(fctCall.getAnnotations()); + } } SourceLocation sourceLoc = select.getSourceLocation(); @@ -142,8 +154,9 @@ public class DisjunctivePredicateToJoinRule implements IAlgebraicRewriteRule { ILogicalExpression cExp = new ConstantExpression(new AsterixConstantValue(list)); Mutable<ILogicalExpression> mutCExp = new MutableObject<>(cExp); - IFunctionInfo scanFctInfo = BuiltinFunctions.getAsterixFunctionInfo(BuiltinFunctions.SCAN_COLLECTION); - UnnestingFunctionCallExpression scanExp = new UnnestingFunctionCallExpression(scanFctInfo, mutCExp); + UnnestingFunctionCallExpression scanExp = new UnnestingFunctionCallExpression( + BuiltinFunctions.getAsterixFunctionInfo(BuiltinFunctions.SCAN_COLLECTION)); + scanExp.getArguments().add(mutCExp); scanExp.setSourceLocation(sourceLoc); LogicalVariable scanVar = context.newVar(); UnnestOperator unn = new UnnestOperator(scanVar, new MutableObject<>(scanExp)); @@ -158,11 +171,14 @@ public class DisjunctivePredicateToJoinRule implements IAlgebraicRewriteRule { scanVarRef.setSourceLocation(sourceLoc); eqExp.getArguments().add(new MutableObject<>(scanVarRef)); eqExp.getArguments().add(new MutableObject<>(varEx.cloneExpression())); - eqExp.getAnnotations().put(IndexedNLJoinExpressionAnnotation.INSTANCE, - IndexedNLJoinExpressionAnnotation.INSTANCE); + if (!allAnnotations.containsKey(SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE)) { + eqExp.getAnnotations().put(IndexedNLJoinExpressionAnnotation.INSTANCE, + IndexedNLJoinExpressionAnnotation.INSTANCE); + } BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation(); bcast.setObject(BroadcastExpressionAnnotation.BroadcastSide.LEFT); // Broadcast the OR predicates branch. eqExp.getAnnotations().put(bcast, bcast); + eqExp.getAnnotations().putAll(allAnnotations); InnerJoinOperator jOp = new InnerJoinOperator(new MutableObject<>(eqExp)); jOp.setSourceLocation(sourceLoc); diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java index 5363ae2..2cd402f 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java @@ -109,6 +109,7 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCa import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression; +import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation; import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression; @@ -978,7 +979,9 @@ public class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTransla QuantifiedPair qp = qe.getQuantifiedList().get(0); VariableExpr varExpr = qp.getVarExpr(); - List<Expression> operandExprs = ((OperatorExpr) qe.getSatisfiesExpr()).getExprList(); + OperatorExpr condExpr = (OperatorExpr) qe.getSatisfiesExpr(); + List<IExpressionAnnotation> condExprHints = condExpr.getHints(); + List<Expression> operandExprs = condExpr.getExprList(); int varIdx = operandExprs.indexOf(varExpr); Expression operandExpr = operandExprs.get(1 - varIdx); @@ -1011,7 +1014,7 @@ public class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTransla throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, sourceLoc, itemExpr.getKind()); } - ILogicalExpression eqExpr = createEqExpr(operandVar, inValue, sourceLoc); + ILogicalExpression eqExpr = createEqExpr(operandVar, inValue, condExprHints, sourceLoc); disjuncts.add(new MutableObject<>(eqExpr)); } break; @@ -1022,7 +1025,7 @@ public class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTransla inVarCursor.reset(); while (inVarCursor.next()) { IAObject inValue = inVarCursor.get(); - ILogicalExpression eqExpr = createEqExpr(operandVar, inValue, sourceLoc); + ILogicalExpression eqExpr = createEqExpr(operandVar, inValue, condExprHints, sourceLoc); disjuncts.add(new MutableObject<>(eqExpr)); } break; @@ -1030,25 +1033,25 @@ public class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTransla throw new IllegalStateException(String.valueOf(inExpr.getKind())); } - MutableObject<ILogicalExpression> condExpr; + MutableObject<ILogicalExpression> disjunctiveExpr; if (disjuncts.size() == 1) { - condExpr = disjuncts.get(0); + disjunctiveExpr = disjuncts.get(0); } else { AbstractFunctionCallExpression orExpr = createFunctionCallExpressionForBuiltinOperator(OperatorType.OR, sourceLoc); orExpr.getArguments().addAll(disjuncts); - condExpr = new MutableObject<>(orExpr); + disjunctiveExpr = new MutableObject<>(orExpr); } LogicalVariable assignVar = context.newVar(); - AssignOperator assignOp = new AssignOperator(assignVar, condExpr); + AssignOperator assignOp = new AssignOperator(assignVar, disjunctiveExpr); assignOp.getInputs().add(topOp); assignOp.setSourceLocation(sourceLoc); return new Pair<>(assignOp, assignVar); } - private ILogicalExpression createEqExpr(LogicalVariable lhsVar, IAObject rhsValue, SourceLocation sourceLoc) - throws CompilationException { + private ILogicalExpression createEqExpr(LogicalVariable lhsVar, IAObject rhsValue, + List<IExpressionAnnotation> hints, SourceLocation sourceLoc) throws CompilationException { VariableReferenceExpression lhsExpr = new VariableReferenceExpression(lhsVar); lhsExpr.setSourceLocation(sourceLoc); ILogicalExpression rhsExpr = translateConstantValue(rhsValue, sourceLoc); @@ -1056,6 +1059,11 @@ public class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTransla createFunctionCallExpressionForBuiltinOperator(OperatorType.EQ, sourceLoc); opExpr.getArguments().add(new MutableObject<>(lhsExpr)); opExpr.getArguments().add(new MutableObject<>(rhsExpr)); + if (hints != null) { + for (IExpressionAnnotation hint : hints) { + opExpr.getAnnotations().put(hint, hint); + } + } return opExpr; } diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-3.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-3.sqlpp new file mode 100644 index 0000000..d634a26 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-3.sqlpp @@ -0,0 +1,43 @@ +/* + * 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. + */ +/* + * Description : Skip secondary index for IN operator + * Expected Res : Success + */ + +drop dataverse test if exists; +create dataverse test; + +use test; + +create type test.TestType as +{ + id : integer, + fname : string, + lname : string +}; + +create dataset testdst(TestType) primary key id; + +create index sec_Idx on testdst (fname) type btree; + +select element emp +from testdst as emp +where emp.fname /*+ skip-index */ in ['Max', 'Roger'] +; diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-3.plan new file mode 100644 index 0000000..87bb65f --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-3.plan @@ -0,0 +1,15 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- HYBRID_HASH_JOIN [$$14][$$17] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- UNNEST |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| \ No newline at end of file diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java index 23b4d60..9c49071 100644 --- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java +++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/OperatorExpressionVisitor.java @@ -103,6 +103,7 @@ public class OperatorExpressionVisitor extends AbstractSqlppExpressionScopingVis comparison.addOperand(itemExpr); comparison.addOperand(bindingVar); comparison.setCurrentop(true); + comparison.addHints(operatorExpr.getHints()); comparison.setSourceLocation(operatorExpr.getSourceLocation()); if (opType == OperatorType.IN) { comparison.addOperator(OperatorType.EQ);
