You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by im...@apache.org on 2015/08/25 18:44:29 UTC
[41/51] [partial] incubator-asterixdb git commit: Change folder
structure for Java repackage
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
deleted file mode 100644
index 22f3b80..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
-import edu.uci.ics.asterix.aql.util.FunctionUtils;
-import edu.uci.ics.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
-import edu.uci.ics.asterix.common.config.DatasetConfig.DatasetType;
-import edu.uci.ics.asterix.common.config.DatasetConfig.IndexType;
-import edu.uci.ics.asterix.metadata.entities.Dataset;
-import edu.uci.ics.asterix.metadata.entities.Index;
-import edu.uci.ics.asterix.om.types.ARecordType;
-import edu.uci.ics.asterix.optimizer.rules.util.EquivalenceClassUtils;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions.ComparisonKind;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractDataSourceOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator.ExecutionMode;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.ExternalDataLookupOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator;
-
-/**
- * Class for helping rewrite rules to choose and apply BTree indexes.
- */
-public class BTreeAccessMethod implements IAccessMethod {
-
- // Describes whether a search predicate is an open/closed interval.
- private enum LimitType {
- LOW_INCLUSIVE,
- LOW_EXCLUSIVE,
- HIGH_INCLUSIVE,
- HIGH_EXCLUSIVE,
- EQUAL
- }
-
- // TODO: There is some redundancy here, since these are listed in AlgebricksBuiltinFunctions as well.
- private static List<FunctionIdentifier> funcIdents = new ArrayList<FunctionIdentifier>();
- static {
- funcIdents.add(AlgebricksBuiltinFunctions.EQ);
- funcIdents.add(AlgebricksBuiltinFunctions.LE);
- funcIdents.add(AlgebricksBuiltinFunctions.GE);
- funcIdents.add(AlgebricksBuiltinFunctions.LT);
- funcIdents.add(AlgebricksBuiltinFunctions.GT);
- }
-
- public static BTreeAccessMethod INSTANCE = new BTreeAccessMethod();
-
- @Override
- public List<FunctionIdentifier> getOptimizableFunctions() {
- return funcIdents;
- }
-
- @Override
- public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) {
- boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
- if (!matches) {
- matches = AccessMethodUtils.analyzeFuncExprArgsForTwoVars(funcExpr, analysisCtx);
- }
- return matches;
- }
-
- @Override
- public boolean matchAllIndexExprs() {
- return false;
- }
-
- @Override
- public boolean matchPrefixIndexExprs() {
- return true;
- }
-
- @Override
- public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef,
- OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx,
- IOptimizationContext context) throws AlgebricksException {
- SelectOperator select = (SelectOperator) selectRef.getValue();
- Mutable<ILogicalExpression> conditionRef = select.getCondition();
- ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(selectRef, conditionRef, subTree, null,
- chosenIndex, analysisCtx, false, false, false, context);
- if (primaryIndexUnnestOp == null) {
- return false;
- }
- Mutable<ILogicalOperator> opRef = (subTree.assignsAndUnnestsRefs.isEmpty()) ? null
- : subTree.assignsAndUnnestsRefs.get(0);
- ILogicalOperator op = null;
- if (opRef != null) {
- op = opRef.getValue();
- }
- // Generate new select using the new condition.
- if (conditionRef.getValue() != null) {
- select.getInputs().clear();
- if (op != null) {
- subTree.dataSourceRef.setValue(primaryIndexUnnestOp);
- select.getInputs().add(new MutableObject<ILogicalOperator>(op));
- } else {
- select.getInputs().add(new MutableObject<ILogicalOperator>(primaryIndexUnnestOp));
- }
- } else {
- ((AbstractLogicalOperator) primaryIndexUnnestOp).setExecutionMode(ExecutionMode.PARTITIONED);
- if (op != null) {
- subTree.dataSourceRef.setValue(primaryIndexUnnestOp);
- selectRef.setValue(op);
- } else {
- selectRef.setValue(primaryIndexUnnestOp);
- }
- }
- return true;
- }
-
- @Override
- public boolean applyJoinPlanTransformation(Mutable<ILogicalOperator> joinRef,
- OptimizableOperatorSubTree leftSubTree, OptimizableOperatorSubTree rightSubTree, Index chosenIndex,
- AccessMethodAnalysisContext analysisCtx, IOptimizationContext context, boolean isLeftOuterJoin,
- boolean hasGroupBy) throws AlgebricksException {
- AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) joinRef.getValue();
- Mutable<ILogicalExpression> conditionRef = joinOp.getCondition();
- // Determine if the index is applicable on the left or right side (if both, we arbitrarily prefer the left side).
- Dataset dataset = analysisCtx.indexDatasetMap.get(chosenIndex);
- // Determine probe and index subtrees based on chosen index.
- OptimizableOperatorSubTree indexSubTree = null;
- OptimizableOperatorSubTree probeSubTree = null;
- if (!isLeftOuterJoin && leftSubTree.hasDataSourceScan()
- && dataset.getDatasetName().equals(leftSubTree.dataset.getDatasetName())) {
- indexSubTree = leftSubTree;
- probeSubTree = rightSubTree;
- } else if (rightSubTree.hasDataSourceScan()
- && dataset.getDatasetName().equals(rightSubTree.dataset.getDatasetName())) {
- indexSubTree = rightSubTree;
- probeSubTree = leftSubTree;
- }
- if (indexSubTree == null) {
- //This may happen for left outer join case
- return false;
- }
-
- LogicalVariable newNullPlaceHolderVar = null;
- if (isLeftOuterJoin) {
- //get a new null place holder variable that is the first field variable of the primary key
- //from the indexSubTree's datasourceScanOp
- newNullPlaceHolderVar = indexSubTree.getDataSourceVariables().get(0);
- }
-
- ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(joinRef, conditionRef, indexSubTree,
- probeSubTree, chosenIndex, analysisCtx, true, isLeftOuterJoin, true, context);
- if (primaryIndexUnnestOp == null) {
- return false;
- }
-
- if (isLeftOuterJoin && hasGroupBy) {
- //reset the null place holder variable
- AccessMethodUtils.resetLOJNullPlaceholderVariableInGroupByOp(analysisCtx, newNullPlaceHolderVar, context);
- }
-
- // If there are conditions left, add a new select operator on top.
- indexSubTree.dataSourceRef.setValue(primaryIndexUnnestOp);
- if (conditionRef.getValue() != null) {
- SelectOperator topSelect = new SelectOperator(conditionRef, isLeftOuterJoin, newNullPlaceHolderVar);
- topSelect.getInputs().add(indexSubTree.rootRef);
- topSelect.setExecutionMode(ExecutionMode.LOCAL);
- context.computeAndSetTypeEnvironmentForOperator(topSelect);
- // Replace the original join with the new subtree rooted at the select op.
- joinRef.setValue(topSelect);
- } else {
- joinRef.setValue(indexSubTree.rootRef.getValue());
- }
- return true;
- }
-
- private ILogicalOperator createSecondaryToPrimaryPlan(Mutable<ILogicalOperator> topOpRef,
- Mutable<ILogicalExpression> conditionRef, OptimizableOperatorSubTree indexSubTree,
- OptimizableOperatorSubTree probeSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx,
- boolean retainInput, boolean retainNull, boolean requiresBroadcast, IOptimizationContext context)
- throws AlgebricksException {
- Dataset dataset = indexSubTree.dataset;
- ARecordType recordType = indexSubTree.recordType;
- // we made sure indexSubTree has datasource scan
- AbstractDataSourceOperator dataSourceOp = (AbstractDataSourceOperator) indexSubTree.dataSourceRef.getValue();
- List<Pair<Integer, Integer>> exprAndVarList = analysisCtx.indexExprsAndVars.get(chosenIndex);
- List<IOptimizableFuncExpr> matchedFuncExprs = analysisCtx.matchedFuncExprs;
- int numSecondaryKeys = analysisCtx.indexNumMatchedKeys.get(chosenIndex);
- // List of function expressions that will be replaced by the secondary-index search.
- // These func exprs will be removed from the select condition at the very end of this method.
- Set<ILogicalExpression> replacedFuncExprs = new HashSet<ILogicalExpression>();
-
- // Info on high and low keys for the BTree search predicate.
- ILogicalExpression[] lowKeyExprs = new ILogicalExpression[numSecondaryKeys];
- ILogicalExpression[] highKeyExprs = new ILogicalExpression[numSecondaryKeys];
- LimitType[] lowKeyLimits = new LimitType[numSecondaryKeys];
- LimitType[] highKeyLimits = new LimitType[numSecondaryKeys];
- boolean[] lowKeyInclusive = new boolean[numSecondaryKeys];
- boolean[] highKeyInclusive = new boolean[numSecondaryKeys];
-
- // TODO: For now we don't do any sophisticated analysis of the func exprs to come up with "the best" range predicate.
- // If we can't figure out how to integrate a certain funcExpr into the current predicate, we just bail by setting this flag.
- boolean couldntFigureOut = false;
- boolean doneWithExprs = false;
- boolean isEqCondition = false;
- // TODO: For now don't consider prefix searches.
- BitSet setLowKeys = new BitSet(numSecondaryKeys);
- BitSet setHighKeys = new BitSet(numSecondaryKeys);
- // Go through the func exprs listed as optimizable by the chosen index,
- // and formulate a range predicate on the secondary-index keys.
-
- // checks whether a type casting happened from a real (FLOAT, DOUBLE) value to an INT value
- // since we have a round issues when dealing with LT(<) OR GT(>) operator.
- boolean realTypeConvertedToIntegerType = false;
-
- for (Pair<Integer, Integer> exprIndex : exprAndVarList) {
- // Position of the field of matchedFuncExprs.get(exprIndex) in the chosen index's indexed exprs.
- IOptimizableFuncExpr optFuncExpr = matchedFuncExprs.get(exprIndex.first);
- int keyPos = indexOf(optFuncExpr.getFieldName(0), chosenIndex.getKeyFieldNames());
- if (keyPos < 0) {
- if (optFuncExpr.getNumLogicalVars() > 1) {
- // If we are optimizing a join, the matching field may be the second field name.
- keyPos = indexOf(optFuncExpr.getFieldName(1), chosenIndex.getKeyFieldNames());
- }
- }
- if (keyPos < 0) {
- throw new AlgebricksException(
- "Could not match optimizable function expression to any index field name.");
- }
- Pair<ILogicalExpression, Boolean> returnedSearchKeyExpr = AccessMethodUtils.createSearchKeyExpr(
- optFuncExpr, indexSubTree, probeSubTree);
- ILogicalExpression searchKeyExpr = returnedSearchKeyExpr.first;
- realTypeConvertedToIntegerType = returnedSearchKeyExpr.second;
-
- LimitType limit = getLimitType(optFuncExpr, probeSubTree);
-
- // If a DOUBLE or FLOAT constant is converted to an INT type value,
- // we need to check a corner case where two real values are located between an INT value.
- // For example, for the following query,
- //
- // for $emp in dataset empDataset
- // where $emp.age > double("2.3") and $emp.age < double("3.3")
- // return $emp.id;
- //
- // It should generate a result if there is a tuple that satisfies the condition, which is 3,
- // however, it does not generate the desired result since finding candidates
- // fail after truncating the fraction part (there is no INT whose value is greater than 2 and less than 3.)
- //
- // Therefore, we convert LT(<) to LE(<=) and GT(>) to GE(>=) to find candidates.
- // This does not change the result of an actual comparison since this conversion is only applied
- // for finding candidates from an index.
- //
- if (realTypeConvertedToIntegerType) {
- if (limit == LimitType.HIGH_EXCLUSIVE) {
- limit = LimitType.HIGH_INCLUSIVE;
- } else if (limit == LimitType.LOW_EXCLUSIVE) {
- limit = LimitType.LOW_INCLUSIVE;
- }
- }
-
- switch (limit) {
- case EQUAL: {
- if (lowKeyLimits[keyPos] == null && highKeyLimits[keyPos] == null) {
- lowKeyLimits[keyPos] = highKeyLimits[keyPos] = limit;
- lowKeyInclusive[keyPos] = highKeyInclusive[keyPos] = true;
- lowKeyExprs[keyPos] = highKeyExprs[keyPos] = searchKeyExpr;
- setLowKeys.set(keyPos);
- setHighKeys.set(keyPos);
- isEqCondition = true;
- } else {
- // Has already been set to the identical values. When optimizing join we may encounter the same optimizable expression twice
- // (once from analyzing each side of the join)
- if (lowKeyLimits[keyPos] == limit && lowKeyInclusive[keyPos] == true
- && lowKeyExprs[keyPos].equals(searchKeyExpr) && highKeyLimits[keyPos] == limit
- && highKeyInclusive[keyPos] == true && highKeyExprs[keyPos].equals(searchKeyExpr)) {
- isEqCondition = true;
- break;
- }
- couldntFigureOut = true;
- }
- // TODO: For now don't consider prefix searches.
- // If high and low keys are set, we exit for now.
- if (setLowKeys.cardinality() == numSecondaryKeys && setHighKeys.cardinality() == numSecondaryKeys) {
- doneWithExprs = true;
- }
- break;
- }
- case HIGH_EXCLUSIVE: {
- if (highKeyLimits[keyPos] == null || (highKeyLimits[keyPos] != null && highKeyInclusive[keyPos])) {
- highKeyLimits[keyPos] = limit;
- highKeyExprs[keyPos] = searchKeyExpr;
- highKeyInclusive[keyPos] = false;
- } else {
- // Has already been set to the identical values. When optimizing join we may encounter the same optimizable expression twice
- // (once from analyzing each side of the join)
- if (highKeyLimits[keyPos] == limit && highKeyInclusive[keyPos] == false
- && highKeyExprs[keyPos].equals(searchKeyExpr)) {
- break;
- }
- couldntFigureOut = true;
- doneWithExprs = true;
- }
- break;
- }
- case HIGH_INCLUSIVE: {
- if (highKeyLimits[keyPos] == null) {
- highKeyLimits[keyPos] = limit;
- highKeyExprs[keyPos] = searchKeyExpr;
- highKeyInclusive[keyPos] = true;
- } else {
- // Has already been set to the identical values. When optimizing join we may encounter the same optimizable expression twice
- // (once from analyzing each side of the join)
- if (highKeyLimits[keyPos] == limit && highKeyInclusive[keyPos] == true
- && highKeyExprs[keyPos].equals(searchKeyExpr)) {
- break;
- }
- couldntFigureOut = true;
- doneWithExprs = true;
- }
- break;
- }
- case LOW_EXCLUSIVE: {
- if (lowKeyLimits[keyPos] == null || (lowKeyLimits[keyPos] != null && lowKeyInclusive[keyPos])) {
- lowKeyLimits[keyPos] = limit;
- lowKeyExprs[keyPos] = searchKeyExpr;
- lowKeyInclusive[keyPos] = false;
- } else {
- // Has already been set to the identical values. When optimizing join we may encounter the same optimizable expression twice
- // (once from analyzing each side of the join)
- if (lowKeyLimits[keyPos] == limit && lowKeyInclusive[keyPos] == false
- && lowKeyExprs[keyPos].equals(searchKeyExpr)) {
- break;
- }
- couldntFigureOut = true;
- doneWithExprs = true;
- }
- break;
- }
- case LOW_INCLUSIVE: {
- if (lowKeyLimits[keyPos] == null) {
- lowKeyLimits[keyPos] = limit;
- lowKeyExprs[keyPos] = searchKeyExpr;
- lowKeyInclusive[keyPos] = true;
- } else {
- // Has already been set to the identical values. When optimizing join we may encounter the same optimizable expression twice
- // (once from analyzing each side of the join)
- if (lowKeyLimits[keyPos] == limit && lowKeyInclusive[keyPos] == true
- && lowKeyExprs[keyPos].equals(searchKeyExpr)) {
- break;
- }
- couldntFigureOut = true;
- doneWithExprs = true;
- }
- break;
- }
- default: {
- throw new IllegalStateException();
- }
- }
- if (!couldntFigureOut) {
- // Remember to remove this funcExpr later.
- replacedFuncExprs.add(matchedFuncExprs.get(exprIndex.first).getFuncExpr());
- }
- if (doneWithExprs) {
- break;
- }
- }
- if (couldntFigureOut) {
- return null;
- }
-
- // If the select condition contains mixed open/closed intervals on multiple keys, then we make all intervals closed to obtain a superset of answers and leave the original selection in place.
- boolean primaryIndexPostProccessingIsNeeded = false;
- for (int i = 1; i < numSecondaryKeys; ++i) {
- if (lowKeyInclusive[i] != lowKeyInclusive[0]) {
- Arrays.fill(lowKeyInclusive, true);
- primaryIndexPostProccessingIsNeeded = true;
- break;
- }
- }
- for (int i = 1; i < numSecondaryKeys; ++i) {
- if (highKeyInclusive[i] != highKeyInclusive[0]) {
- Arrays.fill(highKeyInclusive, true);
- primaryIndexPostProccessingIsNeeded = true;
- break;
- }
- }
-
- // determine cases when prefix search could be applied
- for (int i = 1; i < lowKeyExprs.length; i++) {
- if (lowKeyLimits[0] == null && lowKeyLimits[i] != null || lowKeyLimits[0] != null
- && lowKeyLimits[i] == null || highKeyLimits[0] == null && highKeyLimits[i] != null
- || highKeyLimits[0] != null && highKeyLimits[i] == null) {
- numSecondaryKeys--;
- primaryIndexPostProccessingIsNeeded = true;
- }
- }
- if (lowKeyLimits[0] == null) {
- lowKeyInclusive[0] = true;
- }
- if (highKeyLimits[0] == null) {
- highKeyInclusive[0] = true;
- }
-
- // Here we generate vars and funcs for assigning the secondary-index keys to be fed into the secondary-index search.
- // List of variables for the assign.
- ArrayList<LogicalVariable> keyVarList = new ArrayList<LogicalVariable>();
- // List of variables and expressions for the assign.
- ArrayList<LogicalVariable> assignKeyVarList = new ArrayList<LogicalVariable>();
- ArrayList<Mutable<ILogicalExpression>> assignKeyExprList = new ArrayList<Mutable<ILogicalExpression>>();
- int numLowKeys = createKeyVarsAndExprs(numSecondaryKeys, lowKeyLimits, lowKeyExprs, assignKeyVarList,
- assignKeyExprList, keyVarList, context);
- int numHighKeys = createKeyVarsAndExprs(numSecondaryKeys, highKeyLimits, highKeyExprs, assignKeyVarList,
- assignKeyExprList, keyVarList, context);
-
- BTreeJobGenParams jobGenParams = new BTreeJobGenParams(chosenIndex.getIndexName(), IndexType.BTREE,
- dataset.getDataverseName(), dataset.getDatasetName(), retainInput, retainNull, requiresBroadcast);
- jobGenParams.setLowKeyInclusive(lowKeyInclusive[0]);
- jobGenParams.setHighKeyInclusive(highKeyInclusive[0]);
- jobGenParams.setIsEqCondition(isEqCondition);
- jobGenParams.setLowKeyVarList(keyVarList, 0, numLowKeys);
- jobGenParams.setHighKeyVarList(keyVarList, numLowKeys, numHighKeys);
-
- ILogicalOperator inputOp = null;
- if (!assignKeyVarList.isEmpty()) {
- // Assign operator that sets the constant secondary-index search-key fields if necessary.
- AssignOperator assignConstantSearchKeys = new AssignOperator(assignKeyVarList, assignKeyExprList);
- // Input to this assign is the EmptyTupleSource (which the dataSourceScan also must have had as input).
- assignConstantSearchKeys.getInputs().add(dataSourceOp.getInputs().get(0));
- assignConstantSearchKeys.setExecutionMode(dataSourceOp.getExecutionMode());
- inputOp = assignConstantSearchKeys;
- } else {
- // All index search keys are variables.
- inputOp = probeSubTree.root;
- }
-
- UnnestMapOperator secondaryIndexUnnestOp = AccessMethodUtils.createSecondaryIndexUnnestMap(dataset, recordType,
- chosenIndex, inputOp, jobGenParams, context, false, retainInput);
-
- // Generate the rest of the upstream plan which feeds the search results into the primary index.
- UnnestMapOperator primaryIndexUnnestOp = null;
- boolean isPrimaryIndex = chosenIndex.isPrimaryIndex();
- if (dataset.getDatasetType() == DatasetType.EXTERNAL) {
- // External dataset
- ExternalDataLookupOperator externalDataAccessOp = AccessMethodUtils.createExternalDataLookupUnnestMap(
- dataSourceOp, dataset, recordType, secondaryIndexUnnestOp, context, chosenIndex, retainInput,
- retainNull);
- indexSubTree.dataSourceRef.setValue(externalDataAccessOp);
- return externalDataAccessOp;
- } else if (!isPrimaryIndex) {
- primaryIndexUnnestOp = AccessMethodUtils.createPrimaryIndexUnnestMap(dataSourceOp, dataset, recordType,
- secondaryIndexUnnestOp, context, true, retainInput, retainNull, false);
-
- // Replace the datasource scan with the new plan rooted at
- // primaryIndexUnnestMap.
- indexSubTree.dataSourceRef.setValue(primaryIndexUnnestOp);
- } else {
- List<Object> primaryIndexOutputTypes = new ArrayList<Object>();
- try {
- AccessMethodUtils.appendPrimaryIndexTypes(dataset, recordType, primaryIndexOutputTypes);
- } catch (IOException e) {
- throw new AlgebricksException(e);
- }
- List<LogicalVariable> scanVariables = dataSourceOp.getVariables();
- primaryIndexUnnestOp = new UnnestMapOperator(scanVariables, secondaryIndexUnnestOp.getExpressionRef(),
- primaryIndexOutputTypes, retainInput);
- primaryIndexUnnestOp.getInputs().add(new MutableObject<ILogicalOperator>(inputOp));
-
- if (!primaryIndexPostProccessingIsNeeded) {
- List<Mutable<ILogicalExpression>> remainingFuncExprs = new ArrayList<Mutable<ILogicalExpression>>();
- getNewConditionExprs(conditionRef, replacedFuncExprs, remainingFuncExprs);
- // Generate new condition.
- if (!remainingFuncExprs.isEmpty()) {
- ILogicalExpression pulledCond = createSelectCondition(remainingFuncExprs);
- conditionRef.setValue(pulledCond);
- } else {
- conditionRef.setValue(null);
- }
- }
-
- // Adds equivalence classes --- one equivalent class between a primary key
- // variable and a record field-access expression.
- EquivalenceClassUtils.addEquivalenceClassesForPrimaryIndexAccess(primaryIndexUnnestOp, scanVariables,
- recordType, dataset, context);
- }
-
- return primaryIndexUnnestOp;
- }
-
- private int createKeyVarsAndExprs(int numKeys, LimitType[] keyLimits, ILogicalExpression[] searchKeyExprs,
- ArrayList<LogicalVariable> assignKeyVarList, ArrayList<Mutable<ILogicalExpression>> assignKeyExprList,
- ArrayList<LogicalVariable> keyVarList, IOptimizationContext context) {
- if (keyLimits[0] == null) {
- return 0;
- }
- for (int i = 0; i < numKeys; i++) {
- ILogicalExpression searchKeyExpr = searchKeyExprs[i];
- LogicalVariable keyVar = null;
- if (searchKeyExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
- keyVar = context.newVar();
- assignKeyExprList.add(new MutableObject<ILogicalExpression>(searchKeyExpr));
- assignKeyVarList.add(keyVar);
- } else {
- keyVar = ((VariableReferenceExpression) searchKeyExpr).getVariableReference();
- }
- keyVarList.add(keyVar);
- }
- return numKeys;
- }
-
- private void getNewConditionExprs(Mutable<ILogicalExpression> conditionRef,
- Set<ILogicalExpression> replacedFuncExprs, List<Mutable<ILogicalExpression>> remainingFuncExprs) {
- remainingFuncExprs.clear();
- if (replacedFuncExprs.isEmpty()) {
- return;
- }
- AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) conditionRef.getValue();
- if (replacedFuncExprs.size() == 1) {
- Iterator<ILogicalExpression> it = replacedFuncExprs.iterator();
- if (!it.hasNext()) {
- return;
- }
- if (funcExpr == it.next()) {
- // There are no remaining function exprs.
- return;
- }
- }
- // The original select cond must be an AND. Check it just to be sure.
- if (funcExpr.getFunctionIdentifier() != AlgebricksBuiltinFunctions.AND) {
- throw new IllegalStateException();
- }
- // Clean the conjuncts.
- for (Mutable<ILogicalExpression> arg : funcExpr.getArguments()) {
- ILogicalExpression argExpr = arg.getValue();
- if (argExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- continue;
- }
- // If the function expression was not replaced by the new index
- // plan, then add it to the list of remaining function expressions.
- if (!replacedFuncExprs.contains(argExpr)) {
- remainingFuncExprs.add(arg);
- }
- }
- }
-
- private <T> int indexOf(T value, List<T> coll) {
- int i = 0;
- for (T member : coll) {
- if (member.equals(value)) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- private LimitType getLimitType(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree probeSubTree) {
- ComparisonKind ck = AlgebricksBuiltinFunctions.getComparisonType(optFuncExpr.getFuncExpr()
- .getFunctionIdentifier());
- LimitType limit = null;
- switch (ck) {
- case EQ: {
- limit = LimitType.EQUAL;
- break;
- }
- case GE: {
- limit = probeIsOnLhs(optFuncExpr, probeSubTree) ? LimitType.HIGH_INCLUSIVE : LimitType.LOW_INCLUSIVE;
- break;
- }
- case GT: {
- limit = probeIsOnLhs(optFuncExpr, probeSubTree) ? LimitType.HIGH_EXCLUSIVE : LimitType.LOW_EXCLUSIVE;
- break;
- }
- case LE: {
- limit = probeIsOnLhs(optFuncExpr, probeSubTree) ? LimitType.LOW_INCLUSIVE : LimitType.HIGH_INCLUSIVE;
- break;
- }
- case LT: {
- limit = probeIsOnLhs(optFuncExpr, probeSubTree) ? LimitType.LOW_EXCLUSIVE : LimitType.HIGH_EXCLUSIVE;
- break;
- }
- case NEQ: {
- limit = null;
- break;
- }
- default: {
- throw new IllegalStateException();
- }
- }
- return limit;
- }
-
- private boolean probeIsOnLhs(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree probeSubTree) {
- if (probeSubTree == null) {
- // We are optimizing a selection query. Search key is a constant. Return true if constant is on lhs.
- return optFuncExpr.getFuncExpr().getArguments().get(0) == optFuncExpr.getConstantVal(0);
- } else {
- // We are optimizing a join query. Determine whether the feeding variable is on the lhs.
- return (optFuncExpr.getOperatorSubTree(0) == null || optFuncExpr.getOperatorSubTree(0) == probeSubTree);
- }
- }
-
- private ILogicalExpression createSelectCondition(List<Mutable<ILogicalExpression>> predList) {
- if (predList.size() > 1) {
- IFunctionInfo finfo = FunctionUtils.getFunctionInfo(AlgebricksBuiltinFunctions.AND);
- return new ScalarFunctionCallExpression(finfo, predList);
- }
- return predList.get(0).getValue();
- }
-
- @Override
- public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) {
- // If we are optimizing a join, check for the indexed nested-loop join hint.
- if (optFuncExpr.getNumLogicalVars() == 2) {
- if (!optFuncExpr.getFuncExpr().getAnnotations().containsKey(IndexedNLJoinExpressionAnnotation.INSTANCE)) {
- return false;
- }
- }
- if (!index.isPrimaryIndex()
- && optFuncExpr.getFuncExpr().getAnnotations()
- .containsKey(SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE)) {
- return false;
- }
- // No additional analysis required for BTrees.
- return true;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeJobGenParams.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeJobGenParams.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeJobGenParams.java
deleted file mode 100644
index a3df9d3..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeJobGenParams.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
-import edu.uci.ics.asterix.common.config.DatasetConfig.IndexType;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-
-/**
- * Helper class for reading and writing job-gen parameters for BTree access methods to
- * and from a list of function arguments, typically of an unnest-map.
- */
-public class BTreeJobGenParams extends AccessMethodJobGenParams {
-
- protected List<LogicalVariable> lowKeyVarList;
- protected List<LogicalVariable> highKeyVarList;
-
- protected boolean lowKeyInclusive;
- protected boolean highKeyInclusive;
- protected boolean isEqCondition;
-
- public BTreeJobGenParams() {
- super();
- }
-
- public BTreeJobGenParams(String indexName, IndexType indexType, String dataverseName, String datasetName,
- boolean retainInput, boolean retainNull, boolean requiresBroadcast) {
- super(indexName, indexType, dataverseName, datasetName, retainInput, retainNull, requiresBroadcast);
- }
-
- public void setLowKeyVarList(List<LogicalVariable> keyVarList, int startIndex, int numKeys) {
- lowKeyVarList = new ArrayList<LogicalVariable>(numKeys);
- setKeyVarList(keyVarList, lowKeyVarList, startIndex, numKeys);
- }
-
- public void setHighKeyVarList(List<LogicalVariable> keyVarList, int startIndex, int numKeys) {
- highKeyVarList = new ArrayList<LogicalVariable>(numKeys);
- setKeyVarList(keyVarList, highKeyVarList, startIndex, numKeys);
- }
-
- private void setKeyVarList(List<LogicalVariable> src, List<LogicalVariable> dest, int startIndex, int numKeys) {
- for (int i = 0; i < numKeys; i++) {
- dest.add(src.get(startIndex + i));
- }
- }
-
- public void setLowKeyInclusive(boolean lowKeyInclusive) {
- this.lowKeyInclusive = lowKeyInclusive;
- }
-
- public void setHighKeyInclusive(boolean highKeyInclusive) {
- this.highKeyInclusive = highKeyInclusive;
- }
-
- public void setIsEqCondition(boolean isEqConsition) {
- this.isEqCondition = isEqConsition;
- }
-
- public void writeToFuncArgs(List<Mutable<ILogicalExpression>> funcArgs) {
- super.writeToFuncArgs(funcArgs);
- writeVarList(lowKeyVarList, funcArgs);
- writeVarList(highKeyVarList, funcArgs);
- writeBoolean(lowKeyInclusive, funcArgs);
- writeBoolean(highKeyInclusive, funcArgs);
- writeBoolean(isEqCondition, funcArgs);
- }
-
- public void readFromFuncArgs(List<Mutable<ILogicalExpression>> funcArgs) {
- super.readFromFuncArgs(funcArgs);
- int index = super.getNumParams();
- lowKeyVarList = new ArrayList<LogicalVariable>();
- highKeyVarList = new ArrayList<LogicalVariable>();
- int nextIndex = readVarList(funcArgs, index, lowKeyVarList);
- nextIndex = readVarList(funcArgs, nextIndex, highKeyVarList);
- nextIndex = readKeyInclusives(funcArgs, nextIndex);
- readIsEqCondition(funcArgs, nextIndex);
- }
-
- private int readKeyInclusives(List<Mutable<ILogicalExpression>> funcArgs, int index) {
- lowKeyInclusive = ((ConstantExpression) funcArgs.get(index).getValue()).getValue().isTrue();
- // Read the next function argument at index + 1.
- highKeyInclusive = ((ConstantExpression) funcArgs.get(index + 1).getValue()).getValue().isTrue();
- // We have read two of the function arguments, so the next index is at index + 2.
- return index + 2;
- }
-
- private void readIsEqCondition(List<Mutable<ILogicalExpression>> funcArgs, int index) {
- isEqCondition = ((ConstantExpression) funcArgs.get(index).getValue()).getValue().isTrue();
- }
-
- private void writeBoolean(boolean val, List<Mutable<ILogicalExpression>> funcArgs) {
- ILogicalExpression keyExpr = val ? ConstantExpression.TRUE : ConstantExpression.FALSE;
- funcArgs.add(new MutableObject<ILogicalExpression>(keyExpr));
- }
-
- public List<LogicalVariable> getLowKeyVarList() {
- return lowKeyVarList;
- }
-
- public List<LogicalVariable> getHighKeyVarList() {
- return highKeyVarList;
- }
-
- public boolean isEqCondition() {
- return isEqCondition;
- }
-
- public boolean isLowKeyInclusive() {
- return lowKeyInclusive;
- }
-
- public boolean isHighKeyInclusive() {
- return highKeyInclusive;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IAccessMethod.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IAccessMethod.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IAccessMethod.java
deleted file mode 100644
index d03d1a0..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IAccessMethod.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-
-import edu.uci.ics.asterix.metadata.entities.Index;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-
-/**
- * Interface that an access method should implement to work with the rewrite
- * rules to apply it for join and/or selection queries. This interface provides
- * methods for analyzing a select/join condition, and for rewriting the plan
- * with a given index.
- */
-public interface IAccessMethod {
-
- /**
- * @return A list of function identifiers that are optimizable by this
- * access method.
- */
- public List<FunctionIdentifier> getOptimizableFunctions();
-
- /**
- * Analyzes the arguments of a given optimizable funcExpr to see if this
- * access method is applicable (e.g., one arg is a constant and one is a
- * var). We assume that the funcExpr has already been determined to be
- * optimizable by this access method based on its function identifier. If
- * funcExpr has been found to be optimizable, this method adds an
- * OptimizableFunction to analysisCtx.matchedFuncExprs for further analysis.
- *
- * @return true if funcExpr is optimizable by this access method, false
- * otherwise
- */
- public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx);
-
- /**
- * Indicates whether all index expressions must be matched in order for this
- * index to be applicable.
- *
- * @return boolean
- */
- public boolean matchAllIndexExprs();
-
- /**
- * Indicates whether this index is applicable if only a prefix of the index
- * expressions are matched.
- *
- * @return boolean
- */
- public boolean matchPrefixIndexExprs();
-
- /**
- * Applies the plan transformation to use chosenIndex to optimize a selection query.
- */
- public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef,
- OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx,
- IOptimizationContext context) throws AlgebricksException;
-
- /**
- * Applies the plan transformation to use chosenIndex to optimize a join query.
- * In the case of a LeftOuterJoin, there may or may not be a needed groupby operation
- * If there is, we will need to include it in the transformation
- */
- public boolean applyJoinPlanTransformation(Mutable<ILogicalOperator> joinRef,
- OptimizableOperatorSubTree leftSubTree, OptimizableOperatorSubTree rightSubTree, Index chosenIndex,
- AccessMethodAnalysisContext analysisCtx, IOptimizationContext context, boolean isLeftOuterJoin,
- boolean hasGroupBy) throws AlgebricksException;
-
- /**
- * Analyzes expr to see whether it is optimizable by the given concrete index.
- *
- * @throws AlgebricksException
- */
- public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) throws AlgebricksException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IOptimizableFuncExpr.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
deleted file mode 100644
index 326d38b..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.util.List;
-
-import edu.uci.ics.asterix.om.types.IAType;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IAlgebricksConstantValue;
-
-/**
- * Describes a function expression that is optimizable by an access method.
- * Provides convenient methods for accessing arguments (constants, variables)
- * and metadata of such a function.
- */
-public interface IOptimizableFuncExpr {
- public AbstractFunctionCallExpression getFuncExpr();
-
- public int getNumLogicalVars();
-
- public int getNumConstantVals();
-
- public LogicalVariable getLogicalVar(int index);
-
- public void setLogicalExpr(int index, ILogicalExpression logExpr);
-
- public ILogicalExpression getLogicalExpr(int index);
-
- public void setFieldName(int index, List<String> fieldName);
-
- public List<String> getFieldName(int index);
-
- public void setFieldType(int index, IAType fieldName);
-
- public IAType getFieldType(int index);
-
- public void setOptimizableSubTree(int index, OptimizableOperatorSubTree subTree);
-
- public OptimizableOperatorSubTree getOperatorSubTree(int index);
-
- public IAlgebricksConstantValue getConstantVal(int index);
-
- public int findLogicalVar(LogicalVariable var);
-
- public int findFieldName(List<String> fieldName);
-
- public void substituteVar(LogicalVariable original, LogicalVariable substitution);
-
- public void setPartialField(boolean partialField);
-
- public boolean containsPartialField();
-
- public void setSourceVar(int index, LogicalVariable var);
-
- public LogicalVariable getSourceVar(int index);
-}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
deleted file mode 100644
index 7d93ecc..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang3.mutable.Mutable;
-
-import edu.uci.ics.asterix.metadata.declared.AqlMetadataProvider;
-import edu.uci.ics.asterix.metadata.entities.Index;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
-
-/**
- * This rule optimizes a join with secondary indexes into an indexed nested-loop join.
- * Matches the following operator pattern:
- * (join) <-- (select)? <-- (assign | unnest)+ <-- (datasource scan)
- * <-- (select)? <-- (assign | unnest)+ <-- (datasource scan | unnest-map)
- * The order of the join inputs does not matter.
- * Replaces the above pattern with the following simplified plan:
- * (select) <-- (assign) <-- (btree search) <-- (sort) <-- (unnest(index search)) <-- (assign) <-- (datasource scan | unnest-map)
- * The sort is optional, and some access methods may choose not to sort.
- * Note that for some index-based optimizations we do not remove the triggering
- * condition from the join, since the secondary index may only act as a filter, and the
- * final verification must still be done with the original join condition.
- * The basic outline of this rule is:
- * 1. Match operator pattern.
- * 2. Analyze join condition to see if there are optimizable functions (delegated to IAccessMethods).
- * 3. Check metadata to see if there are applicable indexes.
- * 4. Choose an index to apply (for now only a single index will be chosen).
- * 5. Rewrite plan using index (delegated to IAccessMethods).
- * For left-outer-join, additional patterns are checked and additional treatment is needed as follows:
- * 1. First it checks if there is a groupByOp above the join: (groupby) <-- (leftouterjoin)
- * 2. Inherently, only the right-subtree of the lojOp can be used as indexSubtree.
- * So, the right-subtree must have at least one applicable index on join field(s)
- * 3. If there is a groupByOp, the null placeholder variable introduced in groupByOp should be taken care of correctly.
- * Here, the primary key variable from datasourceScanOp replaces the introduced null placeholder variable.
- * If the primary key is composite key, then the first variable of the primary key variables becomes the
- * null place holder variable. This null placeholder variable works for all three types of indexes.
- */
-public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethodRule {
-
- protected Mutable<ILogicalOperator> joinRef = null;
- protected AbstractBinaryJoinOperator join = null;
- protected AbstractFunctionCallExpression joinCond = null;
- protected final OptimizableOperatorSubTree leftSubTree = new OptimizableOperatorSubTree();
- protected final OptimizableOperatorSubTree rightSubTree = new OptimizableOperatorSubTree();
- protected boolean isLeftOuterJoin = false;
- protected boolean hasGroupBy = true;
-
- // Register access methods.
- protected static Map<FunctionIdentifier, List<IAccessMethod>> accessMethods = new HashMap<FunctionIdentifier, List<IAccessMethod>>();
- static {
- registerAccessMethod(BTreeAccessMethod.INSTANCE, accessMethods);
- registerAccessMethod(RTreeAccessMethod.INSTANCE, accessMethods);
- registerAccessMethod(InvertedIndexAccessMethod.INSTANCE, accessMethods);
- }
-
- @Override
- public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
- throws AlgebricksException {
- clear();
- setMetadataDeclarations(context);
-
- // Match operator pattern and initialize optimizable sub trees.
- if (!matchesOperatorPattern(opRef, context)) {
- return false;
- }
- // Analyze condition on those optimizable subtrees that have a datasource scan.
- Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new HashMap<IAccessMethod, AccessMethodAnalysisContext>();
- boolean matchInLeftSubTree = false;
- boolean matchInRightSubTree = false;
- if (leftSubTree.hasDataSource()) {
- matchInLeftSubTree = analyzeCondition(joinCond, leftSubTree.assignsAndUnnests, analyzedAMs);
- }
- if (rightSubTree.hasDataSource()) {
- matchInRightSubTree = analyzeCondition(joinCond, rightSubTree.assignsAndUnnests, analyzedAMs);
- }
- if (!matchInLeftSubTree && !matchInRightSubTree) {
- return false;
- }
-
- // Set dataset and type metadata.
- AqlMetadataProvider metadataProvider = (AqlMetadataProvider) context.getMetadataProvider();
- boolean checkLeftSubTreeMetadata = false;
- boolean checkRightSubTreeMetadata = false;
- if (matchInLeftSubTree) {
- checkLeftSubTreeMetadata = leftSubTree.setDatasetAndTypeMetadata(metadataProvider);
- }
- if (matchInRightSubTree) {
- checkRightSubTreeMetadata = rightSubTree.setDatasetAndTypeMetadata(metadataProvider);
- }
- if (!checkLeftSubTreeMetadata && !checkRightSubTreeMetadata) {
- return false;
- }
- if (checkLeftSubTreeMetadata) {
- fillSubTreeIndexExprs(leftSubTree, analyzedAMs, context);
- }
- if (checkRightSubTreeMetadata) {
- fillSubTreeIndexExprs(rightSubTree, analyzedAMs, context);
- }
- pruneIndexCandidates(analyzedAMs);
-
- //Remove possibly chosen indexes from left Tree
- if (isLeftOuterJoin) {
- Iterator<Map.Entry<IAccessMethod, AccessMethodAnalysisContext>> amIt = analyzedAMs.entrySet().iterator();
- // Check applicability of indexes by access method type.
- while (amIt.hasNext()) {
- Map.Entry<IAccessMethod, AccessMethodAnalysisContext> entry = amIt.next();
- AccessMethodAnalysisContext amCtx = entry.getValue();
- Iterator<Map.Entry<Index, List<Pair<Integer, Integer>>>> indexIt = amCtx.indexExprsAndVars.entrySet()
- .iterator();
- while (indexIt.hasNext()) {
- Map.Entry<Index, List<Pair<Integer, Integer>>> indexEntry = indexIt.next();
-
- Index chosenIndex = indexEntry.getKey();
- if (!chosenIndex.getDatasetName().equals(rightSubTree.dataset.getDatasetName())) {
- indexIt.remove();
- }
- }
- }
- }
-
- // Choose index to be applied.
- Pair<IAccessMethod, Index> chosenIndex = chooseIndex(analyzedAMs);
- if (chosenIndex == null) {
- context.addToDontApplySet(this, join);
- return false;
- }
-
- // Apply plan transformation using chosen index.
- AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(chosenIndex.first);
-
- //For LOJ with GroupBy, prepare objects to reset LOJ nullPlaceHolderVariable in GroupByOp
- if (isLeftOuterJoin && hasGroupBy) {
- analysisCtx.setLOJGroupbyOpRef(opRef);
- ScalarFunctionCallExpression isNullFuncExpr = AccessMethodUtils
- .findLOJIsNullFuncInGroupBy((GroupByOperator) opRef.getValue());
- analysisCtx.setLOJIsNullFuncInGroupBy(isNullFuncExpr);
- }
- boolean res = chosenIndex.first.applyJoinPlanTransformation(joinRef, leftSubTree, rightSubTree,
- chosenIndex.second, analysisCtx, context, isLeftOuterJoin, hasGroupBy);
- if (res) {
- OperatorPropertiesUtil.typeOpRec(opRef, context);
- }
- context.addToDontApplySet(this, join);
- return res;
- }
-
- protected boolean matchesOperatorPattern(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
- // First check that the operator is a join and its condition is a function call.
- AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
- if (context.checkIfInDontApplySet(this, op1)) {
- return false;
- }
-
- boolean isInnerJoin = isInnerJoin(op1);
- isLeftOuterJoin = isLeftOuterJoin(op1);
-
- if (!isInnerJoin && !isLeftOuterJoin) {
- return false;
- }
-
- // Set and analyze select.
- if (isInnerJoin) {
- joinRef = opRef;
- join = (InnerJoinOperator) op1;
- } else {
- joinRef = op1.getInputs().get(0);
- join = (LeftOuterJoinOperator) joinRef.getValue();
- }
-
- // Check that the select's condition is a function call.
- ILogicalExpression condExpr = join.getCondition().getValue();
- if (condExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- return false;
- }
- joinCond = (AbstractFunctionCallExpression) condExpr;
- leftSubTree.initFromSubTree(join.getInputs().get(0));
- rightSubTree.initFromSubTree(join.getInputs().get(1));
- // One of the subtrees must have a datasource scan.
- if (leftSubTree.hasDataSourceScan() || rightSubTree.hasDataSourceScan()) {
- return true;
- }
- return false;
- }
-
- private boolean isLeftOuterJoin(AbstractLogicalOperator op1) {
- if (op1.getInputs().size() != 1) {
- return false;
- }
- if (((AbstractLogicalOperator) op1.getInputs().get(0).getValue()).getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) {
- return false;
- }
- if (op1.getOperatorTag() == LogicalOperatorTag.GROUP) {
- return true;
- }
- hasGroupBy = false;
- return true;
- }
-
- private boolean isInnerJoin(AbstractLogicalOperator op1) {
- return op1.getOperatorTag() == LogicalOperatorTag.INNERJOIN;
- }
-
- @Override
- public Map<FunctionIdentifier, List<IAccessMethod>> getAccessMethods() {
- return accessMethods;
- }
-
- private void clear() {
- joinRef = null;
- join = null;
- joinCond = null;
- isLeftOuterJoin = false;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/34d81630/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
deleted file mode 100644
index e441a20..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright 2009-2013 by The Regents of the University of California
- * Licensed 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 from
- *
- * 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.
- */
-package edu.uci.ics.asterix.optimizer.rules.am;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
-import edu.uci.ics.asterix.common.config.DatasetConfig.DatasetType;
-import edu.uci.ics.asterix.metadata.declared.AqlDataSource;
-import edu.uci.ics.asterix.metadata.declared.AqlMetadataProvider;
-import edu.uci.ics.asterix.metadata.declared.DatasetDataSource;
-import edu.uci.ics.asterix.metadata.entities.Dataset;
-import edu.uci.ics.asterix.metadata.entities.Index;
-import edu.uci.ics.asterix.metadata.utils.DatasetUtils;
-import edu.uci.ics.asterix.om.base.AInt32;
-import edu.uci.ics.asterix.om.base.AString;
-import edu.uci.ics.asterix.om.constants.AsterixConstantValue;
-import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
-import edu.uci.ics.asterix.om.types.ARecordType;
-import edu.uci.ics.asterix.om.types.ATypeTag;
-import edu.uci.ics.asterix.om.types.IAType;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions.ComparisonKind;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
-import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
-
-public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule {
-
- @Override
- public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
- return false;
- }
-
- @Override
- public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
- throws AlgebricksException {
-
- if (!checkIfRuleIsApplicable(opRef, context)) {
- return false;
- }
-
- AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
- ILogicalExpression condExpr = ((SelectOperator) op).getCondition().getValue();
- AccessMethodAnalysisContext analysisCtx = analyzeCondition(condExpr);
- if (analysisCtx.matchedFuncExprs.isEmpty()) {
- return false;
- }
-
- Dataset dataset = getDataset(op, context);
- List<String> filterFieldName = null;
- ARecordType recType = null;
- if (dataset != null && dataset.getDatasetType() == DatasetType.INTERNAL) {
- filterFieldName = DatasetUtils.getFilterField(dataset);
- IAType itemType = ((AqlMetadataProvider) context.getMetadataProvider()).findType(
- dataset.getDataverseName(), dataset.getItemTypeName());
- if (itemType.getTypeTag() == ATypeTag.RECORD) {
- recType = (ARecordType) itemType;
- }
- }
- if (filterFieldName == null || recType == null) {
- return false;
- }
- List<Index> datasetIndexes = ((AqlMetadataProvider) context.getMetadataProvider()).getDatasetIndexes(
- dataset.getDataverseName(), dataset.getDatasetName());
-
- List<IOptimizableFuncExpr> optFuncExprs = new ArrayList<IOptimizableFuncExpr>();
-
- for (int i = 0; i < analysisCtx.matchedFuncExprs.size(); i++) {
- IOptimizableFuncExpr optFuncExpr = analysisCtx.matchedFuncExprs.get(i);
- boolean found = findMacthedExprFieldName(optFuncExpr, op, dataset, recType, datasetIndexes);
- if (found && optFuncExpr.getFieldName(0).equals(filterFieldName)) {
- optFuncExprs.add(optFuncExpr);
- }
- }
- if (optFuncExprs.isEmpty()) {
- return false;
- }
- changePlan(optFuncExprs, op, dataset, context);
-
- OperatorPropertiesUtil.typeOpRec(opRef, context);
- context.addToDontApplySet(this, op);
- return true;
- }
-
- private AssignOperator createAssignOperator(List<IOptimizableFuncExpr> optFuncExprs,
- List<LogicalVariable> minFilterVars, List<LogicalVariable> maxFilterVars, IOptimizationContext context) {
- List<LogicalVariable> assignKeyVarList = new ArrayList<LogicalVariable>();
- List<Mutable<ILogicalExpression>> assignKeyExprList = new ArrayList<Mutable<ILogicalExpression>>();
-
- for (IOptimizableFuncExpr optFuncExpr : optFuncExprs) {
- ComparisonKind ck = AlgebricksBuiltinFunctions.getComparisonType(optFuncExpr.getFuncExpr()
- .getFunctionIdentifier());
- ILogicalExpression searchKeyExpr = new ConstantExpression(optFuncExpr.getConstantVal(0));
- LogicalVariable var = context.newVar();
- assignKeyExprList.add(new MutableObject<ILogicalExpression>(searchKeyExpr));
- assignKeyVarList.add(var);
- if (ck == ComparisonKind.GE || ck == ComparisonKind.GT) {
- minFilterVars.add(var);
- } else if (ck == ComparisonKind.LE || ck == ComparisonKind.LT) {
- maxFilterVars.add(var);
- } else if (ck == ComparisonKind.EQ) {
- minFilterVars.add(var);
- maxFilterVars.add(var);
- }
- }
- return new AssignOperator(assignKeyVarList, assignKeyExprList);
- }
-
- private void changePlan(List<IOptimizableFuncExpr> optFuncExprs, AbstractLogicalOperator op, Dataset dataset,
- IOptimizationContext context) throws AlgebricksException {
-
- AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
- while (descendantOp != null) {
- if (descendantOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
- DataSourceScanOperator dataSourceScanOp = (DataSourceScanOperator) descendantOp;
- AqlDataSource ds = (AqlDataSource) dataSourceScanOp.getDataSource();
- if (dataset.getDatasetName().compareTo(((DatasetDataSource) ds).getDataset().getDatasetName()) == 0) {
- List<LogicalVariable> minFilterVars = new ArrayList<LogicalVariable>();
- List<LogicalVariable> maxFilterVars = new ArrayList<LogicalVariable>();
-
- AssignOperator assignOp = createAssignOperator(optFuncExprs, minFilterVars, maxFilterVars, context);
-
- dataSourceScanOp.setMinFilterVars(minFilterVars);
- dataSourceScanOp.setMaxFilterVars(maxFilterVars);
-
- List<Mutable<ILogicalExpression>> additionalFilteringExpressions = new ArrayList<Mutable<ILogicalExpression>>();;
- for (LogicalVariable var : assignOp.getVariables()) {
- additionalFilteringExpressions.add(new MutableObject<ILogicalExpression>(
- new VariableReferenceExpression(var)));
- }
-
- dataSourceScanOp.setAdditionalFilteringExpressions(additionalFilteringExpressions);
-
- assignOp.getInputs().add(
- new MutableObject<ILogicalOperator>(dataSourceScanOp.getInputs().get(0).getValue()));
- dataSourceScanOp.getInputs().get(0).setValue(assignOp);
- }
- } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.UNNEST_MAP) {
- UnnestMapOperator unnestMapOp = (UnnestMapOperator) descendantOp;
- ILogicalExpression unnestExpr = unnestMapOp.getExpressionRef().getValue();
- if (unnestExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) unnestExpr;
- FunctionIdentifier fid = f.getFunctionIdentifier();
- if (!fid.equals(AsterixBuiltinFunctions.INDEX_SEARCH)) {
- throw new IllegalStateException();
- }
- AccessMethodJobGenParams jobGenParams = new AccessMethodJobGenParams();
- jobGenParams.readFromFuncArgs(f.getArguments());
- if (dataset.getDatasetName().compareTo(jobGenParams.datasetName) == 0) {
- List<LogicalVariable> minFilterVars = new ArrayList<LogicalVariable>();
- List<LogicalVariable> maxFilterVars = new ArrayList<LogicalVariable>();
-
- AssignOperator assignOp = createAssignOperator(optFuncExprs, minFilterVars, maxFilterVars,
- context);
-
- unnestMapOp.setMinFilterVars(minFilterVars);
- unnestMapOp.setMaxFilterVars(maxFilterVars);
-
- List<Mutable<ILogicalExpression>> additionalFilteringExpressions = new ArrayList<Mutable<ILogicalExpression>>();;
- for (LogicalVariable var : assignOp.getVariables()) {
- additionalFilteringExpressions.add(new MutableObject<ILogicalExpression>(
- new VariableReferenceExpression(var)));
- }
- unnestMapOp.setAdditionalFilteringExpressions(additionalFilteringExpressions);
- assignOp.getInputs().add(
- new MutableObject<ILogicalOperator>(unnestMapOp.getInputs().get(0).getValue()));
- unnestMapOp.getInputs().get(0).setValue(assignOp);
- }
- }
- }
- if (descendantOp.getInputs().isEmpty()) {
- break;
- }
- descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue();
- }
- }
-
- private Dataset getDataset(AbstractLogicalOperator op, IOptimizationContext context) throws AlgebricksException {
- AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
- while (descendantOp != null) {
- if (descendantOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
- DataSourceScanOperator dataSourceScanOp = (DataSourceScanOperator) descendantOp;
- AqlDataSource ds = (AqlDataSource) dataSourceScanOp.getDataSource();
- return ((DatasetDataSource) ds).getDataset();
- } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.UNNEST_MAP) {
- UnnestMapOperator unnestMapOp = (UnnestMapOperator) descendantOp;
- ILogicalExpression unnestExpr = unnestMapOp.getExpressionRef().getValue();
- if (unnestExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) unnestExpr;
- FunctionIdentifier fid = f.getFunctionIdentifier();
- if (!fid.equals(AsterixBuiltinFunctions.INDEX_SEARCH)) {
- throw new IllegalStateException();
- }
- AccessMethodJobGenParams jobGenParams = new AccessMethodJobGenParams();
- jobGenParams.readFromFuncArgs(f.getArguments());
- return ((AqlMetadataProvider) context.getMetadataProvider()).findDataset(
- jobGenParams.dataverseName, jobGenParams.datasetName);
- }
- }
- if (descendantOp.getInputs().isEmpty()) {
- break;
- }
- descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue();
- }
- return null;
- }
-
- private boolean checkIfRuleIsApplicable(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
- // First check that the operator is a select and its condition is a function call.
- AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
- if (context.checkIfInDontApplySet(this, op)) {
- return false;
- }
- if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
- return false;
- }
-
- ILogicalExpression condExpr = ((SelectOperator) op).getCondition().getValue();
- if (condExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- return false;
- }
- return true;
- }
-
- private AccessMethodAnalysisContext analyzeCondition(ILogicalExpression cond) {
- AccessMethodAnalysisContext analysisCtx = new AccessMethodAnalysisContext();
- AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) cond;
- FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
- if (funcIdent != AlgebricksBuiltinFunctions.OR) {
- analyzeFunctionExpr(funcExpr, analysisCtx);
- for (Mutable<ILogicalExpression> arg : funcExpr.getArguments()) {
- ILogicalExpression argExpr = arg.getValue();
- if (argExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- continue;
- }
- analyzeFunctionExpr((AbstractFunctionCallExpression) argExpr, analysisCtx);
- }
- }
- return analysisCtx;
- }
-
- private void analyzeFunctionExpr(AbstractFunctionCallExpression funcExpr, AccessMethodAnalysisContext analysisCtx) {
- FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
- if (funcIdent == AlgebricksBuiltinFunctions.LE || funcIdent == AlgebricksBuiltinFunctions.GE
- || funcIdent == AlgebricksBuiltinFunctions.LT || funcIdent == AlgebricksBuiltinFunctions.GT
- || funcIdent == AlgebricksBuiltinFunctions.EQ) {
- AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
- }
- }
-
- private boolean findMacthedExprFieldName(IOptimizableFuncExpr optFuncExpr, AbstractLogicalOperator op,
- Dataset dataset, ARecordType recType, List<Index> datasetIndexes) throws AlgebricksException {
- AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
- while (descendantOp != null) {
- if (descendantOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
- AssignOperator assignOp = (AssignOperator) descendantOp;
- List<LogicalVariable> varList = assignOp.getVariables();
- for (int varIndex = 0; varIndex < varList.size(); varIndex++) {
- LogicalVariable var = varList.get(varIndex);
- int funcVarIndex = optFuncExpr.findLogicalVar(var);
- if (funcVarIndex == -1) {
- continue;
- }
- List<String> fieldName = getFieldNameFromSubAssignTree(optFuncExpr, descendantOp, varIndex, recType).second;
- if (fieldName == null) {
- return false;
- }
- optFuncExpr.setFieldName(funcVarIndex, fieldName);
- return true;
- }
- } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
- DataSourceScanOperator scanOp = (DataSourceScanOperator) descendantOp;
- List<LogicalVariable> varList = scanOp.getVariables();
- for (int varIndex = 0; varIndex < varList.size(); varIndex++) {
- LogicalVariable var = varList.get(varIndex);
- int funcVarIndex = optFuncExpr.findLogicalVar(var);
- if (funcVarIndex == -1) {
- continue;
- }
- // The variable value is one of the partitioning fields.
- List<String> fieldName = DatasetUtils.getPartitioningKeys(dataset).get(varIndex);
- if (fieldName == null) {
- return false;
- }
- optFuncExpr.setFieldName(funcVarIndex, fieldName);
- return true;
- }
- } else if (descendantOp.getOperatorTag() == LogicalOperatorTag.UNNEST_MAP) {
- UnnestMapOperator unnestMapOp = (UnnestMapOperator) descendantOp;
- List<LogicalVariable> varList = unnestMapOp.getVariables();
- for (int varIndex = 0; varIndex < varList.size(); varIndex++) {
- LogicalVariable var = varList.get(varIndex);
- int funcVarIndex = optFuncExpr.findLogicalVar(var);
- if (funcVarIndex == -1) {
- continue;
- }
-
- String indexName = null;
- Index index = null;
- ILogicalExpression unnestExpr = unnestMapOp.getExpressionRef().getValue();
- if (unnestExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) unnestExpr;
- FunctionIdentifier fid = f.getFunctionIdentifier();
- if (!fid.equals(AsterixBuiltinFunctions.INDEX_SEARCH)) {
- throw new IllegalStateException();
- }
- AccessMethodJobGenParams jobGenParams = new AccessMethodJobGenParams();
- jobGenParams.readFromFuncArgs(f.getArguments());
- indexName = jobGenParams.indexName;
- for (Index idx : datasetIndexes) {
- if (idx.getIndexName().compareTo(indexName) == 0) {
- index = idx;
- break;
- }
- }
- }
-
- int numSecondaryKeys = AccessMethodUtils.getNumSecondaryKeys(index, recType);
- List<String> fieldName;
- if (varIndex >= numSecondaryKeys) {
- fieldName = DatasetUtils.getPartitioningKeys(dataset).get(varIndex - numSecondaryKeys);
- } else {
- fieldName = index.getKeyFieldNames().get(varIndex);
- }
- if (fieldName == null) {
- return false;
- }
- optFuncExpr.setFieldName(funcVarIndex, fieldName);
- return true;
- }
- }
-
- if (descendantOp.getInputs().isEmpty()) {
- break;
- }
- descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue();
- }
- return false;
- }
-
- private Pair<ARecordType, List<String>> getFieldNameFromSubAssignTree(IOptimizableFuncExpr optFuncExpr,
- AbstractLogicalOperator op, int varIndex, ARecordType recType) {
- AbstractLogicalExpression expr = null;
- if (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
- AssignOperator assignOp = (AssignOperator) op;
- expr = (AbstractLogicalExpression) assignOp.getExpressions().get(varIndex).getValue();
- }
- if (expr == null || expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
- return null;
- }
- AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
- FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
- if (funcIdent == AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME
- || funcIdent == AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX) {
-
- //get the variable from here. Figure out which input it came from. Go to that input!!!
- ArrayList<LogicalVariable> usedVars = new ArrayList<LogicalVariable>();
- expr.getUsedVariables(usedVars);
- LogicalVariable usedVar = usedVars.get(0);
- List<String> returnList = new ArrayList<String>();
-
- //Find the input that it came from
- for (int varCheck = 0; varCheck < op.getInputs().size(); varCheck++) {
- AbstractLogicalOperator nestedOp = (AbstractLogicalOperator) op.getInputs().get(varCheck).getValue();
- if (nestedOp.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
- if (varCheck == op.getInputs().size() - 1) {
-
- }
- } else {
- int nestedAssignVar = ((AssignOperator) nestedOp).getVariables().indexOf(usedVar);
- if (nestedAssignVar == -1) {
- continue;
- }
- //get the nested info from the lower input
- Pair<ARecordType, List<String>> lowerInfo = getFieldNameFromSubAssignTree(optFuncExpr,
- (AbstractLogicalOperator) op.getInputs().get(varCheck).getValue(), nestedAssignVar, recType);
- if (lowerInfo != null) {
- recType = lowerInfo.first;
- returnList = lowerInfo.second;
- }
- }
- }
-
- if (funcIdent == AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME) {
- ILogicalExpression nameArg = funcExpr.getArguments().get(1).getValue();
- if (nameArg.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
- return null;
- }
- ConstantExpression constExpr = (ConstantExpression) nameArg;
- returnList.addAll(Arrays.asList(((AString) ((AsterixConstantValue) constExpr.getValue()).getObject())
- .getStringValue()));
- return new Pair<ARecordType, List<String>>(recType, returnList);
- } else if (funcIdent == AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX) {
- ILogicalExpression idxArg = funcExpr.getArguments().get(1).getValue();
- if (idxArg.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
- return null;
- }
- ConstantExpression constExpr = (ConstantExpression) idxArg;
- int fieldIndex = ((AInt32) ((AsterixConstantValue) constExpr.getValue()).getObject()).getIntegerValue();
- returnList.addAll(Arrays.asList(recType.getFieldNames()[fieldIndex]));
- IAType subType = recType.getFieldTypes()[fieldIndex];
- if (subType.getTypeTag() == ATypeTag.RECORD) {
- recType = (ARecordType) subType;
- }
- return new Pair<ARecordType, List<String>>(recType, returnList);
- }
-
- }
-
- ILogicalExpression argExpr = funcExpr.getArguments().get(0).getValue();
- if (argExpr.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
- return null;
- }
-
- return null;
- }
-}
\ No newline at end of file