use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ConsolidateSelectsRule method rewritePre.
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
return false;
}
SelectOperator firstSelect = (SelectOperator) op;
IFunctionInfo andFn = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.AND);
// New conjuncts for consolidated select.
AbstractFunctionCallExpression conj = null;
AbstractLogicalOperator topMostOp = null;
AbstractLogicalOperator selectParent = null;
AbstractLogicalOperator nextSelect = firstSelect;
do {
// Skip through assigns.
do {
selectParent = nextSelect;
nextSelect = (AbstractLogicalOperator) selectParent.getInputs().get(0).getValue();
} while (nextSelect.getOperatorTag() == LogicalOperatorTag.ASSIGN && OperatorPropertiesUtil.isMovable(nextSelect));
// Stop if the child op is not a select.
if (nextSelect.getOperatorTag() != LogicalOperatorTag.SELECT) {
break;
}
// Remember the top-most op that we are not removing.
topMostOp = selectParent;
// Initialize the new conjuncts, if necessary.
if (conj == null) {
conj = new ScalarFunctionCallExpression(andFn);
// Add the first select's condition.
conj.getArguments().add(new MutableObject<ILogicalExpression>(firstSelect.getCondition().getValue()));
}
// Consolidate all following selects.
do {
// Add the condition nextSelect to the new list of conjuncts.
conj.getArguments().add(((SelectOperator) nextSelect).getCondition());
selectParent = nextSelect;
nextSelect = (AbstractLogicalOperator) nextSelect.getInputs().get(0).getValue();
} while (nextSelect.getOperatorTag() == LogicalOperatorTag.SELECT);
// Hook up the input of the top-most remaining op if necessary.
if (topMostOp.getOperatorTag() == LogicalOperatorTag.ASSIGN || topMostOp == firstSelect) {
topMostOp.getInputs().set(0, selectParent.getInputs().get(0));
}
// Prepare for next iteration.
nextSelect = selectParent;
} while (true);
// Did we consolidate any selects?
if (conj == null) {
return false;
}
// Set the new conjuncts.
firstSelect.getCondition().setValue(conj);
context.computeAndSetTypeEnvironmentForOperator(firstSelect);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ExtractFunctionsFromJoinConditionRule method assignFunctionExpressions.
private boolean assignFunctionExpressions(AbstractLogicalOperator joinOp, ILogicalExpression expr, IOptimizationContext context) throws AlgebricksException {
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression fexp = (AbstractFunctionCallExpression) expr;
FunctionIdentifier fi = fexp.getFunctionIdentifier();
boolean modified = false;
if (fi.equals(AlgebricksBuiltinFunctions.AND) || fi.equals(AlgebricksBuiltinFunctions.OR) || processArgumentsToFunction(fi)) {
for (Mutable<ILogicalExpression> a : fexp.getArguments()) {
if (assignFunctionExpressions(joinOp, a.getValue(), context)) {
modified = true;
}
}
return modified;
} else if (AlgebricksBuiltinFunctions.isComparisonFunction(fi) || isComparisonFunction(fi)) {
for (Mutable<ILogicalExpression> exprRef : fexp.getArguments()) {
if (exprRef.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
LogicalVariable newVar = context.newVar();
AssignOperator newAssign = new AssignOperator(newVar, new MutableObject<ILogicalExpression>(exprRef.getValue().cloneExpression()));
newAssign.setExecutionMode(joinOp.getExecutionMode());
// Place assign below joinOp.
List<LogicalVariable> used = new ArrayList<LogicalVariable>();
VariableUtilities.getUsedVariables(newAssign, used);
Mutable<ILogicalOperator> leftBranchRef = joinOp.getInputs().get(0);
ILogicalOperator leftBranch = leftBranchRef.getValue();
List<LogicalVariable> leftBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(leftBranch, leftBranchVariables);
if (leftBranchVariables.containsAll(used)) {
// place assign on left branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(leftBranch));
leftBranchRef.setValue(newAssign);
modified = true;
} else {
Mutable<ILogicalOperator> rightBranchRef = joinOp.getInputs().get(1);
ILogicalOperator rightBranch = rightBranchRef.getValue();
List<LogicalVariable> rightBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(rightBranch, rightBranchVariables);
if (rightBranchVariables.containsAll(used)) {
// place assign on right branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(rightBranch));
rightBranchRef.setValue(newAssign);
modified = true;
}
}
if (modified) {
// Replace original expr with variable reference.
exprRef.setValue(new VariableReferenceExpression(newVar));
context.computeAndSetTypeEnvironmentForOperator(newAssign);
context.computeAndSetTypeEnvironmentForOperator(joinOp);
}
}
}
return modified;
} else {
return false;
}
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ExtractCommonExpressionsRule method isEqJoinCondition.
private boolean isEqJoinCondition(ILogicalExpression expr) {
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
if (funcExpr.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.EQ)) {
ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE && arg2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
return true;
}
}
return false;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class RTreeAccessMethod method createSecondaryToPrimaryPlan.
private ILogicalOperator createSecondaryToPrimaryPlan(OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, boolean retainInput, boolean retainNull, boolean requiresBroadcast, IOptimizationContext context) throws AlgebricksException {
IOptimizableFuncExpr optFuncExpr = AccessMethodUtils.chooseFirstOptFuncExpr(chosenIndex, analysisCtx);
Dataset dataset = indexSubTree.getDataset();
ARecordType recordType = indexSubTree.getRecordType();
ARecordType metaRecordType = indexSubTree.getMetaRecordType();
int optFieldIdx = AccessMethodUtils.chooseFirstOptFuncVar(chosenIndex, analysisCtx);
Pair<IAType, Boolean> keyPairType = Index.getNonNullableOpenFieldType(optFuncExpr.getFieldType(optFieldIdx), optFuncExpr.getFieldName(optFieldIdx), recordType);
if (keyPairType == null) {
return null;
}
// Get the number of dimensions corresponding to the field indexed by chosenIndex.
IAType spatialType = keyPairType.first;
int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
int numSecondaryKeys = numDimensions * 2;
// we made sure indexSubTree has datasource scan
AbstractDataSourceOperator dataSourceOp = (AbstractDataSourceOperator) indexSubTree.getDataSourceRef().getValue();
RTreeJobGenParams jobGenParams = new RTreeJobGenParams(chosenIndex.getIndexName(), IndexType.RTREE, dataset.getDataverseName(), dataset.getDatasetName(), retainInput, requiresBroadcast);
// A spatial object is serialized in the constant of the func expr we are optimizing.
// The R-Tree expects as input an MBR represented with 1 field per dimension.
// Here we generate vars and funcs for extracting MBR fields from the constant into fields of a tuple (as the
// R-Tree expects them).
// List of variables for the assign.
ArrayList<LogicalVariable> keyVarList = new ArrayList<>();
// List of expressions for the assign.
ArrayList<Mutable<ILogicalExpression>> keyExprList = new ArrayList<>();
Pair<ILogicalExpression, Boolean> returnedSearchKeyExpr = AccessMethodUtils.createSearchKeyExpr(optFuncExpr, indexSubTree, probeSubTree);
ILogicalExpression searchKeyExpr = returnedSearchKeyExpr.first;
for (int i = 0; i < numSecondaryKeys; i++) {
// The create MBR function "extracts" one field of an MBR around the given spatial object.
AbstractFunctionCallExpression createMBR = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CREATE_MBR));
// Spatial object is the constant from the func expr we are optimizing.
createMBR.getArguments().add(new MutableObject<>(searchKeyExpr));
// The number of dimensions.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(numDimensions)))));
// Which part of the MBR to extract.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(i)))));
// Add a variable and its expr to the lists which will be passed into an assign op.
LogicalVariable keyVar = context.newVar();
keyVarList.add(keyVar);
keyExprList.add(new MutableObject<ILogicalExpression>(createMBR));
}
jobGenParams.setKeyVarList(keyVarList);
// Assign operator that "extracts" the MBR fields from the func-expr constant into a tuple.
AssignOperator assignSearchKeys = new AssignOperator(keyVarList, keyExprList);
if (probeSubTree == null) {
// We are optimizing a selection query.
// Input to this assign is the EmptyTupleSource (which the dataSourceScan also must have had as input).
assignSearchKeys.getInputs().add(new MutableObject<>(OperatorManipulationUtil.deepCopy(dataSourceOp.getInputs().get(0).getValue())));
assignSearchKeys.setExecutionMode(dataSourceOp.getExecutionMode());
} else {
// We are optimizing a join, place the assign op top of the probe subtree.
assignSearchKeys.getInputs().add(probeSubTree.getRootRef());
}
ILogicalOperator secondaryIndexUnnestOp = AccessMethodUtils.createSecondaryIndexUnnestMap(dataset, recordType, metaRecordType, chosenIndex, assignSearchKeys, jobGenParams, context, false, retainInput, retainNull);
// Generate the rest of the upstream plan which feeds the search results into the primary index.
return dataset.getDatasetType() == DatasetType.EXTERNAL ? AccessMethodUtils.createExternalDataLookupUnnestMap(dataSourceOp, dataset, recordType, secondaryIndexUnnestOp, context, retainInput, retainNull) : AccessMethodUtils.createPrimaryIndexUnnestMap(dataSourceOp, dataset, recordType, metaRecordType, secondaryIndexUnnestOp, context, true, retainInput, false, false);
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ResolveVariableRule method rewriteExpressionReference.
// Recursively rewrites for an expression within an operator.
private boolean rewriteExpressionReference(ILogicalOperator op, Mutable<ILogicalExpression> exprRef, Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidateFromParent, Mutable<ILogicalExpression> parentFuncRef, IOptimizationContext context) throws AlgebricksException {
ILogicalExpression expr = exprRef.getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
boolean changed = false;
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidate = resolveFullyQualifiedPath(funcExpr, context);
for (Mutable<ILogicalExpression> funcArgRef : funcExpr.getArguments()) {
if (rewriteExpressionReference(op, funcArgRef, fullyQualifiedDatasetPathCandidate, exprRef, context)) {
changed = true;
}
}
// Cleans up extra scan-collections if there is.
if (changed) {
cleanupScanCollectionForDataset(funcExpr);
}
// Does the actual resolution.
return changed || resolve(op, context, exprRef, fullyQualifiedDatasetPathCandidateFromParent, parentFuncRef);
}
Aggregations