Search in sources :

Example 1 with IVariableTypeEnvironment

use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.

the class InjectTypeCastForSwitchCaseRule method rewriteSwitchCase.

// Injects casts that cast types for different "THEN" and "ELSE" branches.
private boolean rewriteSwitchCase(ILogicalOperator op, AbstractFunctionCallExpression func, IOptimizationContext context) throws AlgebricksException {
    IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
    IAType producedType = (IAType) env.getType(func);
    List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
    int argSize = argRefs.size();
    boolean rewritten = false;
    for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
        Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
        IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
        if (TypeResolverUtil.needsCast(producedType, type)) {
            ILogicalExpression argExpr = argRef.getValue();
            // Injects a cast call to cast the data type to the produced type of the switch-case function call.
            ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
            TypeCastUtils.setRequiredAndInputTypes(castFunc, producedType, type);
            argRef.setValue(castFunc);
            rewritten = true;
        }
    }
    return rewritten;
}
Also used : Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) IAType(org.apache.asterix.om.types.IAType) ScalarFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)

Example 2 with IVariableTypeEnvironment

use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.

the class InjectTypeCastForUnionRule method injectCast.

// Injects a type cast function on one input (indicated by childIndex) of the union all operator if necessary.
private boolean injectCast(UnionAllOperator op, int childIndex, IOptimizationContext context) throws AlgebricksException {
    // Gets the type environments for the union all operator and its child operator with the right child index.
    IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
    Mutable<ILogicalOperator> branchOpRef = op.getInputs().get(childIndex);
    IVariableTypeEnvironment childEnv = context.getOutputTypeEnvironment(branchOpRef.getValue());
    // The two lists are used for the assign operator that calls cast functions.
    List<LogicalVariable> varsToCast = new ArrayList<>();
    List<Mutable<ILogicalExpression>> castFunctionsForLeft = new ArrayList<>();
    // Iterate through all triples.
    List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> triples = op.getVariableMappings();
    for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple : triples) {
        LogicalVariable producedVar = triple.third;
        IAType producedType = (IAType) env.getVarType(producedVar);
        LogicalVariable varToCast = childIndex == 0 ? triple.first : triple.second;
        IAType inputType = (IAType) childEnv.getVarType(varToCast);
        if (!TypeResolverUtil.needsCast(producedType, inputType)) {
            // Continues to the next triple if no cast is neeeded.
            continue;
        }
        LogicalVariable castedVar = context.newVar();
        // Resets triple variables to new variables that bind to the results of type casting.
        triple.first = childIndex == 0 ? castedVar : triple.first;
        triple.second = childIndex > 0 ? castedVar : triple.second;
        ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), new ArrayList<>(Collections.singletonList(new MutableObject<>(new VariableReferenceExpression(varToCast)))));
        TypeCastUtils.setRequiredAndInputTypes(castFunc, producedType, inputType);
        // Adds the variable and function expression into lists, for the assign operator.
        varsToCast.add(castedVar);
        castFunctionsForLeft.add(new MutableObject<>(castFunc));
    }
    if (castFunctionsForLeft.isEmpty()) {
        return false;
    }
    // Injects an assign operator to perform type casts.
    AssignOperator assignOp = new AssignOperator(varsToCast, castFunctionsForLeft);
    assignOp.getInputs().add(new MutableObject<>(branchOpRef.getValue()));
    branchOpRef.setValue(assignOp);
    context.computeAndSetTypeEnvironmentForOperator(assignOp);
    // Returns true to indicate that rewriting happens.
    return true;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) AssignOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator) Triple(org.apache.hyracks.algebricks.common.utils.Triple) Mutable(org.apache.commons.lang3.mutable.Mutable) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) IAType(org.apache.asterix.om.types.IAType) ScalarFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)

Example 3 with IVariableTypeEnvironment

use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.

the class IntroduceDynamicTypeCastRule method rewritePost.

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    // Depending on the operator type, we need to extract the following pieces of information.
    AbstractLogicalOperator op;
    ARecordType requiredRecordType;
    LogicalVariable recordVar;
    // We identify INSERT and DISTRIBUTE_RESULT operators.
    AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
    switch(op1.getOperatorTag()) {
        case SINK:
        case DELEGATE_OPERATOR:
            {
                /**
                 * pattern match: commit insert assign
                 * resulting plan: commit-insert-project-assign
                 */
                if (op1.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR) {
                    DelegateOperator eOp = (DelegateOperator) op1;
                    if (!(eOp.getDelegate() instanceof CommitOperator)) {
                        return false;
                    }
                }
                AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
                if (op2.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE_UPSERT) {
                    InsertDeleteUpsertOperator insertDeleteOp = (InsertDeleteUpsertOperator) op2;
                    if (insertDeleteOp.getOperation() == InsertDeleteUpsertOperator.Kind.DELETE) {
                        return false;
                    }
                    // Remember this is the operator we need to modify
                    op = insertDeleteOp;
                    // Derive the required ARecordType based on the schema of the DataSource
                    InsertDeleteUpsertOperator insertDeleteOperator = (InsertDeleteUpsertOperator) op2;
                    DataSource dataSource = (DataSource) insertDeleteOperator.getDataSource();
                    requiredRecordType = (ARecordType) dataSource.getItemType();
                    // Derive the Variable which we will potentially wrap with cast/null functions
                    ILogicalExpression expr = insertDeleteOperator.getPayloadExpression().getValue();
                    List<LogicalVariable> payloadVars = new ArrayList<>();
                    expr.getUsedVariables(payloadVars);
                    recordVar = payloadVars.get(0);
                } else {
                    return false;
                }
                break;
            }
        case DISTRIBUTE_RESULT:
            {
                // First, see if there was an output-record-type specified
                requiredRecordType = (ARecordType) op1.getAnnotations().get("output-record-type");
                if (requiredRecordType == null) {
                    return false;
                }
                // Remember this is the operator we need to modify
                op = op1;
                recordVar = ((VariableReferenceExpression) ((DistributeResultOperator) op).getExpressions().get(0).getValue()).getVariableReference();
                break;
            }
        default:
            {
                return false;
            }
    }
    // Derive the statically-computed type of the record
    IVariableTypeEnvironment env = op.computeOutputTypeEnvironment(context);
    IAType inputRecordType = (IAType) env.getVarType(recordVar);
    /** the input record type can be an union type -- for the case when it comes from a subplan or left-outer join */
    boolean checkUnknown = false;
    while (NonTaggedFormatUtil.isOptional(inputRecordType)) {
        /** while-loop for the case there is a nested multi-level union */
        inputRecordType = ((AUnionType) inputRecordType).getActualType();
        checkUnknown = true;
    }
    /** see whether the input record type needs to be casted */
    boolean cast = !compatible(requiredRecordType, inputRecordType);
    if (checkUnknown) {
        recordVar = addWrapperFunction(requiredRecordType, recordVar, op, context, BuiltinFunctions.CHECK_UNKNOWN);
    }
    if (cast) {
        addWrapperFunction(requiredRecordType, recordVar, op, context, BuiltinFunctions.CAST_TYPE);
    }
    return cast || checkUnknown;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) DataSource(org.apache.asterix.metadata.declared.DataSource) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) InsertDeleteUpsertOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator) DelegateOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) ArrayList(java.util.ArrayList) List(java.util.List) ARecordType(org.apache.asterix.om.types.ARecordType) CommitOperator(org.apache.asterix.algebra.operators.CommitOperator) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) IAType(org.apache.asterix.om.types.IAType)

Example 4 with IVariableTypeEnvironment

use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.

the class LoadRecordFieldsRule method findAndEliminateRedundantFieldAccess.

/**
     * Rewrite
     * assign $x := field-access($y, "field")
     * assign $y := record-constructor { "field": Expr, ... }
     * into
     * assign $x := Expr
     * assign $y := record-constructor { "field": Expr, ... }
     */
private static boolean findAndEliminateRedundantFieldAccess(AssignOperator assign, IOptimizationContext context) throws AlgebricksException {
    ILogicalExpression expr = getFirstExpr(assign);
    AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expr;
    ILogicalExpression arg0 = f.getArguments().get(0).getValue();
    if (arg0.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
        return false;
    }
    VariableReferenceExpression vre = (VariableReferenceExpression) arg0;
    LogicalVariable recordVar = vre.getVariableReference();
    ILogicalExpression arg1 = f.getArguments().get(1).getValue();
    if (arg1.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
        return false;
    }
    IVariableTypeEnvironment typeEnvironment = context.getOutputTypeEnvironment(assign);
    ConstantExpression ce = (ConstantExpression) arg1;
    ILogicalExpression fldExpr;
    if (f.getFunctionIdentifier().equals(BuiltinFunctions.FIELD_ACCESS_BY_NAME)) {
        String fldName = ((AString) ((AsterixConstantValue) ce.getValue()).getObject()).getStringValue();
        fldExpr = findFieldExpression(assign, recordVar, fldName, typeEnvironment, (name, expression, env) -> findFieldByNameFromRecordConstructor(name, expression));
    } else if (f.getFunctionIdentifier().equals(BuiltinFunctions.FIELD_ACCESS_BY_INDEX)) {
        Integer fldIdx = ((AInt32) ((AsterixConstantValue) ce.getValue()).getObject()).getIntegerValue();
        fldExpr = findFieldExpression(assign, recordVar, fldIdx, typeEnvironment, LoadRecordFieldsRule::findFieldByIndexFromRecordConstructor);
    } else if (f.getFunctionIdentifier().equals(BuiltinFunctions.FIELD_ACCESS_NESTED)) {
        return false;
    } else {
        throw new IllegalStateException();
    }
    if (fldExpr == null) {
        return false;
    }
    // check the liveness of the new expression
    List<LogicalVariable> usedVariables = new ArrayList<>();
    fldExpr.getUsedVariables(usedVariables);
    List<LogicalVariable> liveInputVars = new ArrayList<>();
    VariableUtilities.getLiveVariables(assign, liveInputVars);
    usedVariables.removeAll(liveInputVars);
    if (usedVariables.isEmpty()) {
        assign.getExpressions().get(0).setValue(fldExpr);
        return true;
    } else {
        return false;
    }
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) OperatorPropertiesUtil(org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil) IOptimizationContext(org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext) NestedTupleSourceOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator) AbstractOperatorWithNestedPlans(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans) ConstantExpressionUtil(org.apache.asterix.om.utils.ConstantExpressionUtil) LogicalExpressionTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag) AbstractLogicalExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression) VariableUtilities(org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ILogicalExpressionReferenceTransform(org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionReferenceTransform) OperatorAnnotation(org.apache.asterix.algebra.base.OperatorAnnotation) ARecordType(org.apache.asterix.om.types.ARecordType) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) AlgebricksBuiltinFunctions(org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions) ILogicalPlan(org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan) IAlgebraicRewriteRule(org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule) FunctionalDependency(org.apache.hyracks.algebricks.core.algebra.properties.FunctionalDependency) LinkedList(java.util.LinkedList) BuiltinFunctions(org.apache.asterix.om.functions.BuiltinFunctions) MutableObject(org.apache.commons.lang3.mutable.MutableObject) LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AString(org.apache.asterix.om.base.AString) Iterator(java.util.Iterator) AsterixConstantValue(org.apache.asterix.om.constants.AsterixConstantValue) AlgebricksException(org.apache.hyracks.algebricks.common.exceptions.AlgebricksException) AssignOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator) LogicalOperatorTag(org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag) ConstantExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) AInt32(org.apache.asterix.om.base.AInt32) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) List(java.util.List) AnalysisUtil(org.apache.asterix.optimizer.base.AnalysisUtil) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) Mutable(org.apache.commons.lang3.mutable.Mutable) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) ConstantExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression) ArrayList(java.util.ArrayList) AString(org.apache.asterix.om.base.AString) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) AsterixConstantValue(org.apache.asterix.om.constants.AsterixConstantValue) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) AString(org.apache.asterix.om.base.AString) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment)

Example 5 with IVariableTypeEnvironment

use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.

the class ExceptionTest method testTypeComputer.

private void testTypeComputer(Class<? extends IResultTypeComputer> c) throws Exception {
    // Mocks the type environment.
    IVariableTypeEnvironment mockTypeEnv = mock(IVariableTypeEnvironment.class);
    // Mocks the metadata provider.
    IMetadataProvider<?, ?> mockMetadataProvider = mock(IMetadataProvider.class);
    // Mocks function expression.
    AbstractFunctionCallExpression mockExpr = mock(AbstractFunctionCallExpression.class);
    FunctionIdentifier fid = mock(FunctionIdentifier.class);
    when(mockExpr.getFunctionIdentifier()).thenReturn(fid);
    when(fid.getName()).thenReturn("testFunction");
    int numCombination = (int) Math.pow(ATypeTag.values().length, 2);
    // Sets two arguments for the mocked function expression.
    for (int index = 0; index < numCombination; ++index) {
        try {
            List<Mutable<ILogicalExpression>> argRefs = new ArrayList<>();
            for (int argIndex = 0; argIndex < 2; ++argIndex) {
                int base = (int) Math.pow(ATypeTag.values().length, argIndex);
                ILogicalExpression mockArg = mock(ILogicalExpression.class);
                argRefs.add(new MutableObject<>(mockArg));
                IAType mockType = mock(IAType.class);
                when(mockTypeEnv.getType(mockArg)).thenReturn(mockType);
                int serializedTypeTag = (index / base) % ATypeTag.values().length + 1;
                ATypeTag typeTag = ATypeTag.VALUE_TYPE_MAPPING[serializedTypeTag];
                if (typeTag == null) {
                    // For some reason, type tag 39 does not exist.
                    typeTag = ATypeTag.ANY;
                }
                when(mockType.getTypeTag()).thenReturn(typeTag);
            }
            // Sets up arguments for the mocked expression.
            when(mockExpr.getArguments()).thenReturn(argRefs);
            // Sets up required/actual types of the mocked expression.
            Object[] opaqueParameters = new Object[2];
            opaqueParameters[0] = BuiltinType.ANY;
            opaqueParameters[1] = BuiltinType.ANY;
            when(mockExpr.getOpaqueParameters()).thenReturn(opaqueParameters);
            // Invokes a type computer.
            IResultTypeComputer instance = (IResultTypeComputer) c.getField("INSTANCE").get(null);
            instance.computeType(mockExpr, mockTypeEnv, mockMetadataProvider);
        } catch (AlgebricksException ae) {
            String msg = ae.getMessage();
            if (msg.startsWith("ASX")) {
                // Verifies the error code.
                int errorCode = Integer.parseInt(msg.substring(3, 7));
                Assert.assertTrue(errorCode >= 1000 && errorCode < 2000);
                continue;
            } else {
                // Any root-level compilation exceptions thrown from type computers should have an error code.
                Assert.assertTrue(!(ae instanceof AlgebricksException) || (ae.getCause() != null));
            }
        } catch (ClassCastException e) {
            continue;
        }
    }
}
Also used : IResultTypeComputer(org.apache.asterix.om.typecomputer.base.IResultTypeComputer) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) ArrayList(java.util.ArrayList) AlgebricksException(org.apache.hyracks.algebricks.common.exceptions.AlgebricksException) FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) ATypeTag(org.apache.asterix.om.types.ATypeTag) MutableObject(org.apache.commons.lang3.mutable.MutableObject) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) IAType(org.apache.asterix.om.types.IAType)

Aggregations

IVariableTypeEnvironment (org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment)51 ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)24 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)23 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)22 IAType (org.apache.asterix.om.types.IAType)15 RecordDescriptor (org.apache.hyracks.api.dataflow.value.RecordDescriptor)14 ArrayList (java.util.ArrayList)13 Mutable (org.apache.commons.lang3.mutable.Mutable)13 AlgebricksException (org.apache.hyracks.algebricks.common.exceptions.AlgebricksException)12 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)12 IOperatorDescriptor (org.apache.hyracks.api.dataflow.IOperatorDescriptor)11 IBinaryComparatorFactory (org.apache.hyracks.api.dataflow.value.IBinaryComparatorFactory)11 AlgebricksPartitionConstraint (org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint)10 Pair (org.apache.hyracks.algebricks.common.utils.Pair)9 IBinaryComparatorFactoryProvider (org.apache.hyracks.algebricks.data.IBinaryComparatorFactoryProvider)9 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)8 INormalizedKeyComputerFactory (org.apache.hyracks.api.dataflow.value.INormalizedKeyComputerFactory)8 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)7 IMetadataProvider (org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider)7 INormalizedKeyComputerFactoryProvider (org.apache.hyracks.algebricks.data.INormalizedKeyComputerFactoryProvider)7