Search in sources :

Example 21 with FunctionIdentifier

use of org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier in project asterixdb by apache.

the class PushAggregateIntoNestedSubplanRule method extractAggFunctionsFromExpression.

/**
     * @param exprRef
     * @param nspWithAgg
     * @param context
     * @return a pair whose first member is a boolean which is true iff
     *         something was changed in the expression tree rooted at expr. The
     *         second member is the result of transforming expr.
     * @throws AlgebricksException
     */
private Pair<Boolean, ILogicalExpression> extractAggFunctionsFromExpression(Mutable<ILogicalExpression> exprRef, Map<LogicalVariable, AbstractOperatorWithNestedPlans> nspWithAgg, Map<ILogicalExpression, ILogicalExpression> aggregateExprToVarExpr, IOptimizationContext context) throws AlgebricksException {
    ILogicalExpression expr = exprRef.getValue();
    switch(expr.getExpressionTag()) {
        case FUNCTION_CALL:
            AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
            FunctionIdentifier fi = BuiltinFunctions.getAggregateFunction(fce.getFunctionIdentifier());
            if (fi != null) {
                ILogicalExpression a1 = fce.getArguments().get(0).getValue();
                if (a1.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
                    LogicalVariable argVar = ((VariableReferenceExpression) a1).getVariableReference();
                    AbstractOperatorWithNestedPlans nspOp = nspWithAgg.get(argVar);
                    if (nspOp != null) {
                        if (!aggregateExprToVarExpr.containsKey(expr)) {
                            LogicalVariable newVar = context.newVar();
                            AggregateFunctionCallExpression aggFun = BuiltinFunctions.makeAggregateFunctionExpression(fi, fce.getArguments());
                            rewriteAggregateInNestedSubplan(argVar, nspOp, aggFun, newVar, context);
                            ILogicalExpression newVarExpr = new VariableReferenceExpression(newVar);
                            aggregateExprToVarExpr.put(expr, newVarExpr);
                            return new Pair<>(Boolean.TRUE, newVarExpr);
                        } else {
                            ILogicalExpression varExpr = aggregateExprToVarExpr.get(expr);
                            return new Pair<>(Boolean.TRUE, varExpr);
                        }
                    }
                }
            }
            boolean change = false;
            for (Mutable<ILogicalExpression> a : fce.getArguments()) {
                Pair<Boolean, ILogicalExpression> aggArg = extractAggFunctionsFromExpression(a, nspWithAgg, aggregateExprToVarExpr, context);
                if (aggArg.first.booleanValue()) {
                    a.setValue(aggArg.second);
                    change = true;
                }
            }
            return new Pair<>(change, fce);
        case VARIABLE:
        case CONSTANT:
            return new Pair<>(Boolean.FALSE, expr);
        default:
            throw new IllegalArgumentException();
    }
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AggregateFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) AbstractOperatorWithNestedPlans(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans) Pair(org.apache.hyracks.algebricks.common.utils.Pair)

Example 22 with FunctionIdentifier

use of org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier in project asterixdb by apache.

the class SimilarityCheckRule method replaceSelectConditionExprs.

private boolean replaceSelectConditionExprs(Mutable<ILogicalExpression> expRef, List<AssignOperator> assigns, IOptimizationContext context) throws AlgebricksException {
    ILogicalExpression expr = expRef.getValue();
    if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
        return false;
    }
    AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
    FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
    // then we may still need the true similarity value even if the GE/GT/LE/LE comparison returns false.
    if (funcIdent == AlgebricksBuiltinFunctions.AND) {
        boolean found = true;
        for (int i = 0; i < funcExpr.getArguments().size(); ++i) {
            found = found && replaceSelectConditionExprs(funcExpr.getArguments().get(i), assigns, context);
        }
        return found;
    }
    // Look for GE/GT/LE/LT.
    if (funcIdent != AlgebricksBuiltinFunctions.GE && funcIdent != AlgebricksBuiltinFunctions.GT && funcIdent != AlgebricksBuiltinFunctions.LE && funcIdent != AlgebricksBuiltinFunctions.LT) {
        return false;
    }
    // One arg should be a function call or a variable, the other a constant.
    AsterixConstantValue constVal = null;
    ILogicalExpression nonConstExpr = null;
    ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
    ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
    // Normalized GE/GT/LE/LT as if constant was on the right hand side.
    FunctionIdentifier normFuncIdent = null;
    // One of the args must be a constant.
    if (arg1.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
        ConstantExpression constExpr = (ConstantExpression) arg1;
        constVal = (AsterixConstantValue) constExpr.getValue();
        nonConstExpr = arg2;
        // Get func ident as if swapping lhs and rhs.
        normFuncIdent = getLhsAndRhsSwappedFuncIdent(funcIdent);
    } else if (arg2.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
        ConstantExpression constExpr = (ConstantExpression) arg2;
        constVal = (AsterixConstantValue) constExpr.getValue();
        nonConstExpr = arg1;
        // Constant is already on rhs, so nothing to be done for normalizedFuncIdent.
        normFuncIdent = funcIdent;
    } else {
        return false;
    }
    // The other arg is a function call. We can directly replace the select condition with an equivalent similarity check expression.
    if (nonConstExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
        return replaceWithFunctionCallArg(expRef, normFuncIdent, constVal, (AbstractFunctionCallExpression) nonConstExpr);
    }
    // The other arg ist a variable. We may have to introduce an assign operator that assigns the result of a similarity-check function to a variable.
    if (nonConstExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
        return replaceWithVariableArg(expRef, normFuncIdent, constVal, (VariableReferenceExpression) nonConstExpr, assigns, context);
    }
    return false;
}
Also used : FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) AsterixConstantValue(org.apache.asterix.om.constants.AsterixConstantValue) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) ConstantExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression)

Example 23 with FunctionIdentifier

use of org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier in project asterixdb by apache.

the class UnnestToDataScanRule method handleFunction.

protected boolean handleFunction(Mutable<ILogicalOperator> opRef, IOptimizationContext context, UnnestOperator unnest, AbstractFunctionCallExpression f) throws AlgebricksException {
    FunctionIdentifier fid = f.getFunctionIdentifier();
    if (fid.equals(BuiltinFunctions.DATASET)) {
        if (unnest.getPositionalVariable() != null) {
            // TODO remove this after enabling the support of positional variables in data scan
            throw new AlgebricksException("No positional variables are allowed over datasets.");
        }
        ILogicalExpression expr = f.getArguments().get(0).getValue();
        if (expr.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
            return false;
        }
        ConstantExpression ce = (ConstantExpression) expr;
        IAlgebricksConstantValue acv = ce.getValue();
        if (!(acv instanceof AsterixConstantValue)) {
            return false;
        }
        AsterixConstantValue acv2 = (AsterixConstantValue) acv;
        if (acv2.getObject().getType().getTypeTag() != ATypeTag.STRING) {
            return false;
        }
        String datasetArg = ((AString) acv2.getObject()).getStringValue();
        MetadataProvider metadataProvider = (MetadataProvider) context.getMetadataProvider();
        Pair<String, String> datasetReference = parseDatasetReference(metadataProvider, datasetArg);
        String dataverseName = datasetReference.first;
        String datasetName = datasetReference.second;
        Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName);
        if (dataset == null) {
            throw new AlgebricksException("Could not find dataset " + datasetName + " in dataverse " + dataverseName);
        }
        DataSourceId asid = new DataSourceId(dataverseName, datasetName);
        List<LogicalVariable> variables = new ArrayList<>();
        if (dataset.getDatasetType() == DatasetType.INTERNAL) {
            int numPrimaryKeys = dataset.getPrimaryKeys().size();
            for (int i = 0; i < numPrimaryKeys; i++) {
                variables.add(context.newVar());
            }
        }
        variables.add(unnest.getVariable());
        DataSource dataSource = metadataProvider.findDataSource(asid);
        boolean hasMeta = dataSource.hasMeta();
        if (hasMeta) {
            variables.add(context.newVar());
        }
        DataSourceScanOperator scan = new DataSourceScanOperator(variables, dataSource);
        List<Mutable<ILogicalOperator>> scanInpList = scan.getInputs();
        scanInpList.addAll(unnest.getInputs());
        opRef.setValue(scan);
        addPrimaryKey(variables, dataSource, context);
        context.computeAndSetTypeEnvironmentForOperator(scan);
        // Adds equivalence classes --- one equivalent class between a primary key
        // variable and a record field-access expression.
        IAType[] schemaTypes = dataSource.getSchemaTypes();
        ARecordType recordType = (ARecordType) (hasMeta ? schemaTypes[schemaTypes.length - 2] : schemaTypes[schemaTypes.length - 1]);
        ARecordType metaRecordType = (ARecordType) (hasMeta ? schemaTypes[schemaTypes.length - 1] : null);
        EquivalenceClassUtils.addEquivalenceClassesForPrimaryIndexAccess(scan, variables, recordType, metaRecordType, dataset, context);
        return true;
    } else if (fid.equals(BuiltinFunctions.FEED_COLLECT)) {
        if (unnest.getPositionalVariable() != null) {
            throw new AlgebricksException("No positional variables are allowed over feeds.");
        }
        String dataverse = ConstantExpressionUtil.getStringArgument(f, 0);
        String sourceFeedName = ConstantExpressionUtil.getStringArgument(f, 1);
        String getTargetFeed = ConstantExpressionUtil.getStringArgument(f, 2);
        String subscriptionLocation = ConstantExpressionUtil.getStringArgument(f, 3);
        String targetDataset = ConstantExpressionUtil.getStringArgument(f, 4);
        String outputType = ConstantExpressionUtil.getStringArgument(f, 5);
        MetadataProvider metadataProvider = (MetadataProvider) context.getMetadataProvider();
        DataSourceId asid = new DataSourceId(dataverse, getTargetFeed);
        String policyName = metadataProvider.getConfig().get(FeedActivityDetails.FEED_POLICY_NAME);
        FeedPolicyEntity policy = metadataProvider.findFeedPolicy(dataverse, policyName);
        if (policy == null) {
            policy = BuiltinFeedPolicies.getFeedPolicy(policyName);
            if (policy == null) {
                throw new AlgebricksException("Unknown feed policy:" + policyName);
            }
        }
        ArrayList<LogicalVariable> feedDataScanOutputVariables = new ArrayList<>();
        String csLocations = metadataProvider.getConfig().get(FeedActivityDetails.COLLECT_LOCATIONS);
        List<LogicalVariable> pkVars = new ArrayList<>();
        FeedDataSource ds = createFeedDataSource(asid, targetDataset, sourceFeedName, subscriptionLocation, metadataProvider, policy, outputType, csLocations, unnest.getVariable(), context, pkVars);
        // The order for feeds is <Record-Meta-PK>
        feedDataScanOutputVariables.add(unnest.getVariable());
        // Does it produce meta?
        if (ds.hasMeta()) {
            feedDataScanOutputVariables.add(context.newVar());
        }
        // Does it produce pk?
        if (ds.isChange()) {
            feedDataScanOutputVariables.addAll(pkVars);
        }
        DataSourceScanOperator scan = new DataSourceScanOperator(feedDataScanOutputVariables, ds);
        List<Mutable<ILogicalOperator>> scanInpList = scan.getInputs();
        scanInpList.addAll(unnest.getInputs());
        opRef.setValue(scan);
        context.computeAndSetTypeEnvironmentForOperator(scan);
        return true;
    }
    return false;
}
Also used : ConstantExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression) ArrayList(java.util.ArrayList) AString(org.apache.asterix.om.base.AString) AsterixConstantValue(org.apache.asterix.om.constants.AsterixConstantValue) DataSourceScanOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator) FeedPolicyEntity(org.apache.asterix.metadata.entities.FeedPolicyEntity) ArrayList(java.util.ArrayList) List(java.util.List) AString(org.apache.asterix.om.base.AString) LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) Dataset(org.apache.asterix.metadata.entities.Dataset) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) AlgebricksException(org.apache.hyracks.algebricks.common.exceptions.AlgebricksException) IAlgebricksConstantValue(org.apache.hyracks.algebricks.core.algebra.expressions.IAlgebricksConstantValue) FeedDataSource(org.apache.asterix.metadata.declared.FeedDataSource) DataSource(org.apache.asterix.metadata.declared.DataSource) FeedDataSource(org.apache.asterix.metadata.declared.FeedDataSource) 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) MetadataProvider(org.apache.asterix.metadata.declared.MetadataProvider) ARecordType(org.apache.asterix.om.types.ARecordType) DataSourceId(org.apache.asterix.metadata.declared.DataSourceId) IAType(org.apache.asterix.om.types.IAType)

Example 24 with FunctionIdentifier

use of org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier in project asterixdb by apache.

the class AbstractIntroduceAccessMethodRule method analyzeFunctionExprAndUpdateAnalyzedAM.

/**
     * Finds applicable access methods for the given function expression based
     * on the function identifier, and an analysis of the function's arguments.
     * Updates the analyzedAMs accordingly.
     *
     * @throws AlgebricksException
     */
protected boolean analyzeFunctionExprAndUpdateAnalyzedAM(AbstractFunctionCallExpression funcExpr, List<AbstractLogicalOperator> assignsAndUnnests, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs, IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
    FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
    if (funcIdent == AlgebricksBuiltinFunctions.AND) {
        return false;
    }
    // Retrieves the list of access methods that are relevant based on the
    // funcIdent.
    List<IAccessMethod> relevantAMs = getAccessMethods().get(funcIdent);
    if (relevantAMs == null) {
        return false;
    }
    boolean atLeastOneMatchFound = false;
    // Place holder for a new analysis context in case we need one.
    AccessMethodAnalysisContext newAnalysisCtx = new AccessMethodAnalysisContext();
    for (IAccessMethod accessMethod : relevantAMs) {
        AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(accessMethod);
        // Use the current place holder.
        if (analysisCtx == null) {
            analysisCtx = newAnalysisCtx;
        }
        // Analyzes the funcExpr's arguments to see if the accessMethod is
        // truly applicable.
        boolean matchFound = accessMethod.analyzeFuncExprArgsAndUpdateAnalysisCtx(funcExpr, assignsAndUnnests, analysisCtx, context, typeEnvironment);
        if (matchFound) {
            // with a new one.
            if (analysisCtx == newAnalysisCtx) {
                analyzedAMs.put(accessMethod, analysisCtx);
                newAnalysisCtx = new AccessMethodAnalysisContext();
            }
            atLeastOneMatchFound = true;
        }
    }
    return atLeastOneMatchFound;
}
Also used : FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier)

Example 25 with FunctionIdentifier

use of org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier in project asterixdb by apache.

the class AbstractScalarAggregateDescriptor method createEvaluatorFactory.

@Override
public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) throws AlgebricksException {
    // The aggregate function will get a SingleFieldFrameTupleReference that points to the result of the ScanCollection.
    // The list-item will always reside in the first field (column) of the SingleFieldFrameTupleReference.
    IScalarEvaluatorFactory[] aggFuncArgs = new IScalarEvaluatorFactory[1];
    aggFuncArgs[0] = new ColumnAccessEvalFactory(0);
    // Create aggregate function from this scalar version.
    FunctionIdentifier fid = BuiltinFunctions.getAggregateFunction(getIdentifier());
    IFunctionManager mgr = FunctionManagerHolder.getFunctionManager();
    IFunctionDescriptor fd = mgr.lookupFunction(fid);
    AbstractAggregateFunctionDynamicDescriptor aggFuncDesc = (AbstractAggregateFunctionDynamicDescriptor) fd;
    final IAggregateEvaluatorFactory aggFuncFactory = aggFuncDesc.createAggregateEvaluatorFactory(aggFuncArgs);
    return new IScalarEvaluatorFactory() {

        private static final long serialVersionUID = 1L;

        @Override
        public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws HyracksDataException {
            // Use ScanCollection to iterate over list items.
            ScanCollectionUnnestingFunctionFactory scanCollectionFactory = new ScanCollectionUnnestingFunctionFactory(args[0]);
            return new GenericScalarAggregateFunction(aggFuncFactory.createAggregateEvaluator(ctx), scanCollectionFactory, ctx);
        }
    };
}
Also used : FunctionIdentifier(org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier) IFunctionDescriptor(org.apache.asterix.om.functions.IFunctionDescriptor) IHyracksTaskContext(org.apache.hyracks.api.context.IHyracksTaskContext) ScanCollectionUnnestingFunctionFactory(org.apache.asterix.runtime.unnestingfunctions.std.ScanCollectionDescriptor.ScanCollectionUnnestingFunctionFactory) ColumnAccessEvalFactory(org.apache.hyracks.algebricks.runtime.evaluators.ColumnAccessEvalFactory) AbstractAggregateFunctionDynamicDescriptor(org.apache.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor) IAggregateEvaluatorFactory(org.apache.hyracks.algebricks.runtime.base.IAggregateEvaluatorFactory) IScalarEvaluatorFactory(org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory) IFunctionManager(org.apache.asterix.om.functions.IFunctionManager)

Aggregations

FunctionIdentifier (org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier)50 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)33 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)31 ArrayList (java.util.ArrayList)15 Mutable (org.apache.commons.lang3.mutable.Mutable)14 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)13 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)11 AlgebricksException (org.apache.hyracks.algebricks.common.exceptions.AlgebricksException)10 ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)10 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)10 MetadataProvider (org.apache.asterix.metadata.declared.MetadataProvider)7 IAType (org.apache.asterix.om.types.IAType)7 AssignOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator)7 List (java.util.List)6 MutableObject (org.apache.commons.lang3.mutable.MutableObject)6 AggregateFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression)6 ConstantExpression (org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression)6 ScalarFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)6 AString (org.apache.asterix.om.base.AString)5 Pair (org.apache.hyracks.algebricks.common.utils.Pair)5