use of org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator in project asterixdb by apache.
the class InjectTypeCastForUnionRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
ILogicalOperator op = opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.UNIONALL) {
return false;
}
UnionAllOperator unionAllOperator = (UnionAllOperator) op;
// Injects casts to the first and second input branch of the UnionAllOperator.
return injectCast(unionAllOperator, 0, context) || injectCast(unionAllOperator, 1, context);
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator in project asterixdb by apache.
the class LogicalOperatorDeepCopyWithNewVariablesVisitor method visitUnionOperator.
@Override
public ILogicalOperator visitUnionOperator(UnionAllOperator op, ILogicalOperator arg) throws AlgebricksException {
List<Mutable<ILogicalOperator>> copiedInputs = new ArrayList<>();
for (Mutable<ILogicalOperator> childRef : op.getInputs()) {
copiedInputs.add(deepCopyOperatorReference(childRef, null));
}
List<List<LogicalVariable>> liveVarsInInputs = new ArrayList<>();
for (Mutable<ILogicalOperator> inputOpRef : copiedInputs) {
List<LogicalVariable> liveVars = new ArrayList<>();
VariableUtilities.getLiveVariables(inputOpRef.getValue(), liveVars);
liveVarsInInputs.add(liveVars);
}
List<LogicalVariable> liveVarsInLeftInput = liveVarsInInputs.get(0);
List<LogicalVariable> liveVarsInRightInput = liveVarsInInputs.get(1);
List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> copiedTriples = new ArrayList<>();
int index = 0;
for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple : op.getVariableMappings()) {
LogicalVariable producedVar = deepCopyVariable(triple.third);
Triple<LogicalVariable, LogicalVariable, LogicalVariable> copiedTriple = new Triple<>(liveVarsInLeftInput.get(index), liveVarsInRightInput.get(index), producedVar);
copiedTriples.add(copiedTriple);
++index;
}
UnionAllOperator opCopy = new UnionAllOperator(copiedTriples);
deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy);
return opCopy;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator in project asterixdb by apache.
the class IsomorphismVariableMappingVisitor method mapVariablesForUnion.
private void mapVariablesForUnion(ILogicalOperator op, ILogicalOperator arg) {
if (op.getOperatorTag() != arg.getOperatorTag()) {
return;
}
UnionAllOperator union = (UnionAllOperator) op;
UnionAllOperator unionArg = (UnionAllOperator) arg;
mapVarTripleList(union.getVariableMappings(), unionArg.getVariableMappings());
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator in project asterixdb by apache.
the class LangExpressionToPlanTranslator method translateUnionAllFromInputExprs.
// Generates the plan for "UNION ALL" or union expression from its input expressions.
protected Pair<ILogicalOperator, LogicalVariable> translateUnionAllFromInputExprs(List<ILangExpression> inputExprs, Mutable<ILogicalOperator> tupSource) throws CompilationException {
List<Mutable<ILogicalOperator>> inputOpRefsToUnion = new ArrayList<>();
List<LogicalVariable> vars = new ArrayList<>();
for (ILangExpression expr : inputExprs) {
// Visits the expression of one branch.
Pair<ILogicalOperator, LogicalVariable> opAndVar = expr.accept(this, tupSource);
// Creates an unnest operator.
LogicalVariable unnestVar = context.newVar();
List<Mutable<ILogicalExpression>> args = new ArrayList<>();
args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(opAndVar.second)));
UnnestOperator unnestOp = new UnnestOperator(unnestVar, new MutableObject<ILogicalExpression>(new UnnestingFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION), args)));
unnestOp.getInputs().add(new MutableObject<>(opAndVar.first));
inputOpRefsToUnion.add(new MutableObject<ILogicalOperator>(unnestOp));
vars.add(unnestVar);
}
// Creates a tree of binary union-all operators.
UnionAllOperator topUnionAllOp = null;
LogicalVariable topUnionVar = null;
Iterator<Mutable<ILogicalOperator>> inputOpRefIterator = inputOpRefsToUnion.iterator();
Mutable<ILogicalOperator> leftInputBranch = inputOpRefIterator.next();
Iterator<LogicalVariable> inputVarIterator = vars.iterator();
LogicalVariable leftInputVar = inputVarIterator.next();
while (inputOpRefIterator.hasNext()) {
// Generates the variable triple <leftVar, rightVar, outputVar> .
topUnionVar = context.newVar();
Triple<LogicalVariable, LogicalVariable, LogicalVariable> varTriple = new Triple<>(leftInputVar, inputVarIterator.next(), topUnionVar);
List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varTriples = new ArrayList<>();
varTriples.add(varTriple);
// Creates a binary union-all operator.
topUnionAllOp = new UnionAllOperator(varTriples);
topUnionAllOp.getInputs().add(leftInputBranch);
topUnionAllOp.getInputs().add(inputOpRefIterator.next());
// Re-assigns leftInputBranch and leftInputVar.
leftInputBranch = new MutableObject<>(topUnionAllOp);
leftInputVar = topUnionVar;
}
return new Pair<>(topUnionAllOp, topUnionVar);
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator in project asterixdb by apache.
the class InvertedIndexAccessMethod method applyJoinPlanTransformation.
@Override
public boolean applyJoinPlanTransformation(Mutable<ILogicalOperator> joinRef, OptimizableOperatorSubTree leftSubTree, OptimizableOperatorSubTree rightSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, IOptimizationContext context, boolean isLeftOuterJoin, boolean hasGroupBy) throws AlgebricksException {
// Figure out if the index is applicable on the left or right side (if both, we arbitrarily prefer the left side).
Dataset dataset = analysisCtx.getDatasetFromIndexDatasetMap(chosenIndex);
OptimizableOperatorSubTree indexSubTree;
OptimizableOperatorSubTree probeSubTree;
// The following is just a sanity check.
if (rightSubTree.hasDataSourceScan() && dataset.getDatasetName().equals(rightSubTree.getDataset().getDatasetName())) {
indexSubTree = rightSubTree;
probeSubTree = leftSubTree;
} else {
return false;
}
IOptimizableFuncExpr optFuncExpr = AccessMethodUtils.chooseFirstOptFuncExpr(chosenIndex, analysisCtx);
// if the dataset of index subtree and the dataset of first argument's subtree is the same
if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CONTAINS && optFuncExpr.getOperatorSubTree(0).getDataset() != null && !optFuncExpr.getOperatorSubTree(0).getDataset().getDatasetName().equals(indexSubTree.getDataset().getDatasetName())) {
return false;
}
//if LOJ, reset null place holder variable
LogicalVariable newNullPlaceHolderVar = null;
if (isLeftOuterJoin && hasGroupBy) {
//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);
//reset the null place holder variable
AccessMethodUtils.resetLOJNullPlaceholderVariableInGroupByOp(analysisCtx, newNullPlaceHolderVar, context);
}
AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) joinRef.getValue();
// Remember the original probe subtree, and its primary-key variables,
// so we can later retrieve the missing attributes via an equi join.
List<LogicalVariable> originalSubTreePKs = new ArrayList<>();
// Remember the primary-keys of the new probe subtree for the top-level equi join.
List<LogicalVariable> surrogateSubTreePKs = new ArrayList<>();
// Copy probe subtree, replacing their variables with new ones. We will use the original variables
// to stitch together a top-level equi join.
Mutable<ILogicalOperator> originalProbeSubTreeRootRef = copyAndReinitProbeSubTree(probeSubTree, join.getCondition().getValue(), optFuncExpr, originalSubTreePKs, surrogateSubTreePKs, context);
// Remember original live variables from the index sub tree.
List<LogicalVariable> indexSubTreeLiveVars = new ArrayList<>();
VariableUtilities.getLiveVariables(indexSubTree.getRoot(), indexSubTreeLiveVars);
// Clone the original join condition because we may have to modify it (and we also need the original).
ILogicalExpression joinCond = join.getCondition().getValue().cloneExpression();
// Create "panic" (non indexed) nested-loop join path if necessary.
Mutable<ILogicalOperator> panicJoinRef = null;
Map<LogicalVariable, LogicalVariable> panicVarMap = null;
if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CHECK || optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CONTAINS) {
panicJoinRef = new MutableObject<>(joinRef.getValue());
panicVarMap = new HashMap<>();
Mutable<ILogicalOperator> newProbeRootRef = createPanicNestedLoopJoinPlan(panicJoinRef, indexSubTree, probeSubTree, optFuncExpr, chosenIndex, panicVarMap, context);
probeSubTree.getRootRef().setValue(newProbeRootRef.getValue());
probeSubTree.setRoot(newProbeRootRef.getValue());
}
// Create regular indexed-nested loop join path.
ILogicalOperator indexPlanRootOp = createSecondaryToPrimaryPlan(null, indexSubTree, probeSubTree, chosenIndex, analysisCtx, true, isLeftOuterJoin, true, context);
indexSubTree.getDataSourceRef().setValue(indexPlanRootOp);
// Change join into a select with the same condition.
SelectOperator topSelect = new SelectOperator(new MutableObject<ILogicalExpression>(joinCond), isLeftOuterJoin, newNullPlaceHolderVar);
topSelect.getInputs().add(indexSubTree.getRootRef());
topSelect.setExecutionMode(ExecutionMode.LOCAL);
context.computeAndSetTypeEnvironmentForOperator(topSelect);
ILogicalOperator topOp = topSelect;
// Hook up the indexed-nested loop join path with the "panic" (non indexed) nested-loop join path by putting a union all on top.
if (panicJoinRef != null) {
LogicalVariable inputSearchVar = getInputSearchVar(optFuncExpr, indexSubTree);
indexSubTreeLiveVars.addAll(originalSubTreePKs);
indexSubTreeLiveVars.add(inputSearchVar);
List<LogicalVariable> panicPlanLiveVars = new ArrayList<>();
VariableUtilities.getLiveVariables(panicJoinRef.getValue(), panicPlanLiveVars);
// Create variable mapping for union all operator.
List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = new ArrayList<>();
for (int i = 0; i < indexSubTreeLiveVars.size(); i++) {
LogicalVariable indexSubTreeVar = indexSubTreeLiveVars.get(i);
LogicalVariable panicPlanVar = panicVarMap.get(indexSubTreeVar);
if (panicPlanVar == null) {
panicPlanVar = indexSubTreeVar;
}
varMap.add(new Triple<LogicalVariable, LogicalVariable, LogicalVariable>(indexSubTreeVar, panicPlanVar, indexSubTreeVar));
}
UnionAllOperator unionAllOp = new UnionAllOperator(varMap);
unionAllOp.getInputs().add(new MutableObject<ILogicalOperator>(topOp));
unionAllOp.getInputs().add(panicJoinRef);
unionAllOp.setExecutionMode(ExecutionMode.PARTITIONED);
context.computeAndSetTypeEnvironmentForOperator(unionAllOp);
topOp = unionAllOp;
}
// Place a top-level equi-join on top to retrieve the missing variables from the original probe subtree.
// The inner (build) branch of the join is the subtree with the data scan, since the result of the similarity join could potentially be big.
// This choice may not always be the most efficient, but it seems more robust than the alternative.
Mutable<ILogicalExpression> eqJoinConditionRef = createPrimaryKeysEqJoinCondition(originalSubTreePKs, surrogateSubTreePKs);
InnerJoinOperator topEqJoin = new InnerJoinOperator(eqJoinConditionRef, originalProbeSubTreeRootRef, new MutableObject<ILogicalOperator>(topOp));
topEqJoin.setExecutionMode(ExecutionMode.PARTITIONED);
joinRef.setValue(topEqJoin);
context.computeAndSetTypeEnvironmentForOperator(topEqJoin);
return true;
}
Aggregations