use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression in project asterixdb by apache.
the class LoadRecordFieldsRule method findFieldExpression.
// Finds a field expression.
private static ILogicalExpression findFieldExpression(AbstractLogicalOperator op, LogicalVariable recordVar, Object accessKey, IVariableTypeEnvironment typeEnvironment, FieldResolver resolver) throws AlgebricksException {
for (Mutable<ILogicalOperator> child : op.getInputs()) {
AbstractLogicalOperator opChild = (AbstractLogicalOperator) child.getValue();
if (opChild.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
AssignOperator op2 = (AssignOperator) opChild;
int i = op2.getVariables().indexOf(recordVar);
if (i >= 0) {
AbstractLogicalExpression constr = (AbstractLogicalExpression) op2.getExpressions().get(i).getValue();
return resolveFieldExpression(constr, accessKey, typeEnvironment, resolver);
}
} else if (opChild.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
NestedTupleSourceOperator nts = (NestedTupleSourceOperator) opChild;
AbstractLogicalOperator opBelowNestedPlan = (AbstractLogicalOperator) nts.getDataSourceReference().getValue().getInputs().get(0).getValue();
ILogicalExpression expr1 = findFieldExpression(opBelowNestedPlan, recordVar, accessKey, typeEnvironment, resolver);
if (expr1 != null) {
return expr1;
}
}
ILogicalExpression expr2 = findFieldExpression(opChild, recordVar, accessKey, typeEnvironment, resolver);
if (expr2 != null) {
return expr2;
}
}
return null;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression in project asterixdb by apache.
the class AbstractIntroduceAccessMethodRule method getFieldNameFromSubTree.
/**
* Returns the field name corresponding to the assigned variable at
* varIndex. Returns null if the expr at varIndex does not yield to a field
* access function after following a set of allowed functions.
*
* @throws AlgebricksException
*/
protected List<String> getFieldNameFromSubTree(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree subTree, int opIndex, int assignVarIndex, ARecordType recordType, int funcVarIndex, ILogicalExpression parentFuncExpr, LogicalVariable recordVar, ARecordType metaType, LogicalVariable metaVar) throws AlgebricksException {
// Get expression corresponding to opVar at varIndex.
AbstractLogicalExpression expr = null;
AbstractFunctionCallExpression childFuncExpr = null;
AbstractLogicalOperator op = subTree.getAssignsAndUnnests().get(opIndex);
if (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
AssignOperator assignOp = (AssignOperator) op;
expr = (AbstractLogicalExpression) assignOp.getExpressions().get(assignVarIndex).getValue();
// Can't get a field name from a constant expression. So, return null.
if (expr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
return Collections.emptyList();
}
childFuncExpr = (AbstractFunctionCallExpression) expr;
} else {
UnnestOperator unnestOp = (UnnestOperator) op;
expr = (AbstractLogicalExpression) unnestOp.getExpressionRef().getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return Collections.emptyList();
}
childFuncExpr = (AbstractFunctionCallExpression) expr;
if (childFuncExpr.getFunctionIdentifier() != BuiltinFunctions.SCAN_COLLECTION) {
return Collections.emptyList();
}
expr = (AbstractLogicalExpression) childFuncExpr.getArguments().get(0).getValue();
}
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return Collections.emptyList();
}
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
boolean isByName = false;
boolean isFieldAccess = false;
String fieldName = null;
List<String> nestedAccessFieldName = null;
int fieldIndex = -1;
if (funcIdent == BuiltinFunctions.FIELD_ACCESS_BY_NAME) {
fieldName = ConstantExpressionUtil.getStringArgument(funcExpr, 1);
if (fieldName == null) {
return Collections.emptyList();
}
isFieldAccess = true;
isByName = true;
} else if (funcIdent == BuiltinFunctions.FIELD_ACCESS_BY_INDEX) {
Integer idx = ConstantExpressionUtil.getIntArgument(funcExpr, 1);
if (idx == null) {
return Collections.emptyList();
}
fieldIndex = idx;
isFieldAccess = true;
} else if (funcIdent == BuiltinFunctions.FIELD_ACCESS_NESTED) {
ILogicalExpression nameArg = funcExpr.getArguments().get(1).getValue();
if (nameArg.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
return Collections.emptyList();
}
ConstantExpression constExpr = (ConstantExpression) nameArg;
AOrderedList orderedNestedFieldName = (AOrderedList) ((AsterixConstantValue) constExpr.getValue()).getObject();
nestedAccessFieldName = new ArrayList<>();
for (int i = 0; i < orderedNestedFieldName.size(); i++) {
nestedAccessFieldName.add(((AString) orderedNestedFieldName.getItem(i)).getStringValue());
}
isFieldAccess = true;
isByName = true;
}
if (isFieldAccess) {
LogicalVariable sourceVar = ((VariableReferenceExpression) funcExpr.getArguments().get(0).getValue()).getVariableReference();
optFuncExpr.setLogicalExpr(funcVarIndex, parentFuncExpr);
int[] assignAndExpressionIndexes = null;
//go forward through nested assigns until you find the relevant one
for (int i = opIndex + 1; i < subTree.getAssignsAndUnnests().size(); i++) {
AbstractLogicalOperator subOp = subTree.getAssignsAndUnnests().get(i);
List<LogicalVariable> varList;
if (subOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
//Nested was an assign
varList = ((AssignOperator) subOp).getVariables();
} else if (subOp.getOperatorTag() == LogicalOperatorTag.UNNEST) {
//Nested is not an assign
varList = ((UnnestOperator) subOp).getVariables();
} else {
break;
}
//Go through variables in assign to check for match
for (int varIndex = 0; varIndex < varList.size(); varIndex++) {
LogicalVariable var = varList.get(varIndex);
ArrayList<LogicalVariable> parentVars = new ArrayList<>();
expr.getUsedVariables(parentVars);
if (parentVars.contains(var)) {
//Found the variable we are looking for.
//return assign and index of expression
int[] returnValues = { i, varIndex };
assignAndExpressionIndexes = returnValues;
}
}
}
if (assignAndExpressionIndexes != null && assignAndExpressionIndexes[0] > -1) {
//We found the nested assign
//Recursive call on nested assign
List<String> parentFieldNames = getFieldNameFromSubTree(optFuncExpr, subTree, assignAndExpressionIndexes[0], assignAndExpressionIndexes[1], recordType, funcVarIndex, parentFuncExpr, recordVar, metaType, metaVar);
if (parentFieldNames.isEmpty()) {
//We will not use index
return Collections.emptyList();
}
if (!isByName) {
fieldName = sourceVar.equals(metaVar) ? ((ARecordType) metaType.getSubFieldType(parentFieldNames)).getFieldNames()[fieldIndex] : ((ARecordType) recordType.getSubFieldType(parentFieldNames)).getFieldNames()[fieldIndex];
}
optFuncExpr.setSourceVar(funcVarIndex, ((AssignOperator) op).getVariables().get(assignVarIndex));
//add fieldName to the nested fieldName, return
if (nestedAccessFieldName != null) {
for (int i = 0; i < nestedAccessFieldName.size(); i++) {
parentFieldNames.add(nestedAccessFieldName.get(i));
}
} else {
parentFieldNames.add(fieldName);
}
return (parentFieldNames);
}
optFuncExpr.setSourceVar(funcVarIndex, ((AssignOperator) op).getVariables().get(assignVarIndex));
//no nested assign, we are at the lowest level.
if (isByName) {
if (nestedAccessFieldName != null) {
return nestedAccessFieldName;
}
return new ArrayList<>(Arrays.asList(fieldName));
}
return new ArrayList<>(Arrays.asList(sourceVar.equals(metaVar) ? metaType.getFieldNames()[fieldIndex] : recordType.getFieldNames()[fieldIndex]));
}
if (!funcIDSetThatRetainFieldName.contains(funcIdent)) {
return Collections.emptyList();
}
// We use a part of the field in edit distance computation
if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CHECK) {
optFuncExpr.setPartialField(true);
}
// We expect the function's argument to be a variable, otherwise we
// cannot apply an index.
ILogicalExpression argExpr = funcExpr.getArguments().get(0).getValue();
if (argExpr.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return Collections.emptyList();
}
LogicalVariable curVar = ((VariableReferenceExpression) argExpr).getVariableReference();
// the current operator
for (int assignOrUnnestIndex = opIndex + 1; assignOrUnnestIndex < subTree.getAssignsAndUnnests().size(); assignOrUnnestIndex++) {
AbstractLogicalOperator curOp = subTree.getAssignsAndUnnests().get(assignOrUnnestIndex);
if (curOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
AssignOperator assignOp = (AssignOperator) curOp;
List<LogicalVariable> varList = assignOp.getVariables();
for (int varIndex = 0; varIndex < varList.size(); varIndex++) {
LogicalVariable var = varList.get(varIndex);
if (var.equals(curVar)) {
optFuncExpr.setSourceVar(funcVarIndex, var);
return getFieldNameFromSubTree(optFuncExpr, subTree, assignOrUnnestIndex, varIndex, recordType, funcVarIndex, childFuncExpr, recordVar, metaType, metaVar);
}
}
} else {
UnnestOperator unnestOp = (UnnestOperator) curOp;
LogicalVariable var = unnestOp.getVariable();
if (var.equals(curVar)) {
getFieldNameFromSubTree(optFuncExpr, subTree, assignOrUnnestIndex, 0, recordType, funcVarIndex, childFuncExpr, recordVar, metaType, metaVar);
}
}
}
return Collections.emptyList();
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression in project asterixdb by apache.
the class RemoveUnusedOneToOneEquiJoinRule method isEquiJoin.
private boolean isEquiJoin(Mutable<ILogicalExpression> conditionExpr) {
AbstractLogicalExpression expr = (AbstractLogicalExpression) conditionExpr.getValue();
if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
if (funcIdent != AlgebricksBuiltinFunctions.AND && funcIdent != AlgebricksBuiltinFunctions.EQ) {
return false;
}
}
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression in project asterixdb by apache.
the class CancelUnnestWithNestedListifyRule method applies.
private boolean applies(Mutable<ILogicalOperator> opRef, Set<LogicalVariable> varUsedAbove, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest1 = (UnnestOperator) op1;
ILogicalExpression expr = unnest1.getExpressionRef().getValue();
LogicalVariable unnestedVar;
switch(expr.getExpressionTag()) {
case VARIABLE:
unnestedVar = ((VariableReferenceExpression) expr).getVariableReference();
break;
case FUNCTION_CALL:
if (((AbstractFunctionCallExpression) expr).getFunctionIdentifier() != BuiltinFunctions.SCAN_COLLECTION) {
return false;
}
AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) expr;
ILogicalExpression functionCallArgExpr = functionCall.getArguments().get(0).getValue();
if (functionCallArgExpr.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
unnestedVar = ((VariableReferenceExpression) functionCallArgExpr).getVariableReference();
break;
default:
return false;
}
if (varUsedAbove.contains(unnestedVar)) {
return false;
}
Mutable<ILogicalOperator> opRef2 = op1.getInputs().get(0);
AbstractLogicalOperator r = (AbstractLogicalOperator) opRef2.getValue();
if (r.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
// go inside of a group-by plan
GroupByOperator gby = (GroupByOperator) r;
if (gby.getNestedPlans().size() != 1) {
return false;
}
if (gby.getNestedPlans().get(0).getRoots().size() != 1) {
return false;
}
AbstractLogicalOperator nestedPlanRoot = (AbstractLogicalOperator) gby.getNestedPlans().get(0).getRoots().get(0).getValue();
if (nestedPlanRoot.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator agg = (AggregateOperator) nestedPlanRoot;
Mutable<ILogicalOperator> aggInputOpRef = agg.getInputs().get(0);
if (agg.getVariables().size() > 1) {
return false;
}
if (OperatorManipulationUtil.ancestorOfOperators(agg, ImmutableSet.of(LogicalOperatorTag.LIMIT, LogicalOperatorTag.ORDER, LogicalOperatorTag.GROUP, LogicalOperatorTag.DISTINCT))) {
return false;
}
LogicalVariable aggVar = agg.getVariables().get(0);
ILogicalExpression aggFun = agg.getExpressions().get(0).getValue();
if (!aggVar.equals(unnestedVar) || ((AbstractLogicalExpression) aggFun).getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) aggFun;
if (!BuiltinFunctions.LISTIFY.equals(f.getFunctionIdentifier())) {
return false;
}
if (f.getArguments().size() != 1) {
return false;
}
ILogicalExpression arg0 = f.getArguments().get(0).getValue();
if (((AbstractLogicalExpression) arg0).getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
LogicalVariable paramVar = ((VariableReferenceExpression) arg0).getVariableReference();
ArrayList<LogicalVariable> assgnVars = new ArrayList<LogicalVariable>(1);
assgnVars.add(unnest1.getVariable());
ArrayList<Mutable<ILogicalExpression>> assgnExprs = new ArrayList<Mutable<ILogicalExpression>>(1);
assgnExprs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(paramVar)));
AssignOperator assign = new AssignOperator(assgnVars, assgnExprs);
LogicalVariable posVar = unnest1.getPositionalVariable();
if (posVar == null) {
// Creates assignment for group-by keys.
ArrayList<LogicalVariable> gbyKeyAssgnVars = new ArrayList<LogicalVariable>();
ArrayList<Mutable<ILogicalExpression>> gbyKeyAssgnExprs = new ArrayList<Mutable<ILogicalExpression>>();
for (int i = 0; i < gby.getGroupByList().size(); i++) {
if (gby.getGroupByList().get(i).first != null) {
gbyKeyAssgnVars.add(gby.getGroupByList().get(i).first);
gbyKeyAssgnExprs.add(gby.getGroupByList().get(i).second);
}
}
// Moves the nested pipeline before aggregation out of the group-by op.
Mutable<ILogicalOperator> bottomOpRef = aggInputOpRef;
AbstractLogicalOperator bottomOp = (AbstractLogicalOperator) bottomOpRef.getValue();
while (bottomOp.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
bottomOpRef = bottomOp.getInputs().get(0);
bottomOp = (AbstractLogicalOperator) bottomOpRef.getValue();
}
// Removes the group-by operator.
opRef.setValue(assign);
assign.getInputs().add(aggInputOpRef);
AssignOperator gbyKeyAssign = new AssignOperator(gbyKeyAssgnVars, gbyKeyAssgnExprs);
gbyKeyAssign.getInputs().add(gby.getInputs().get(0));
bottomOpRef.setValue(gbyKeyAssign);
context.computeAndSetTypeEnvironmentForOperator(gbyKeyAssign);
context.computeAndSetTypeEnvironmentForOperator(assign);
} else {
// if positional variable is used in unnest, the unnest will be pushed into the group-by as a running-aggregate
// First create assign for the unnest variable
List<LogicalVariable> nestedAssignVars = new ArrayList<LogicalVariable>();
List<Mutable<ILogicalExpression>> nestedAssignExprs = new ArrayList<Mutable<ILogicalExpression>>();
nestedAssignVars.add(unnest1.getVariable());
nestedAssignExprs.add(new MutableObject<ILogicalExpression>(arg0));
AssignOperator nestedAssign = new AssignOperator(nestedAssignVars, nestedAssignExprs);
nestedAssign.getInputs().add(opRef2);
// Then create running aggregation for the positional variable
List<LogicalVariable> raggVars = new ArrayList<LogicalVariable>();
List<Mutable<ILogicalExpression>> raggExprs = new ArrayList<Mutable<ILogicalExpression>>();
raggVars.add(posVar);
StatefulFunctionCallExpression fce = new StatefulFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.TID), UnpartitionedPropertyComputer.INSTANCE);
raggExprs.add(new MutableObject<ILogicalExpression>(fce));
RunningAggregateOperator raggOp = new RunningAggregateOperator(raggVars, raggExprs);
raggOp.setExecutionMode(unnest1.getExecutionMode());
RunningAggregatePOperator raggPOp = new RunningAggregatePOperator();
raggOp.setPhysicalOperator(raggPOp);
raggOp.getInputs().add(nestedPlanRoot.getInputs().get(0));
gby.getNestedPlans().get(0).getRoots().set(0, new MutableObject<ILogicalOperator>(raggOp));
opRef.setValue(nestedAssign);
context.computeAndSetTypeEnvironmentForOperator(nestedAssign);
context.computeAndSetTypeEnvironmentForOperator(raggOp);
context.computeAndSetTypeEnvironmentForOperator(gby);
}
return true;
}
Aggregations