Search in sources :

Example 1 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.

the class Evaluator method evaluate.

private Object evaluate(Function function, List<?> tuple) throws BlockedException, TeiidComponentException, ExpressionEvaluationException {
    // Get function based on resolved function info
    FunctionDescriptor fd = function.getFunctionDescriptor();
    // Evaluate args
    Expression[] args = function.getArgs();
    Object[] values = null;
    int start = 0;
    if (fd.requiresContext()) {
        values = new Object[args.length + 1];
        values[0] = context;
        start = 1;
    } else {
        values = new Object[args.length];
    }
    for (int i = 0; i < args.length; i++) {
        values[i + start] = internalEvaluate(args[i], tuple);
        if (values[i + start] instanceof Constant) {
            // $NON-NLS-1$
            throw new AssertionError("Multi-valued constant not allowed to be directly evaluated");
        }
    }
    if (fd.getPushdown() == PushDown.MUST_PUSHDOWN) {
        try {
            return evaluatePushdown(function, tuple, values);
        } catch (TeiidProcessingException e) {
            throw new ExpressionEvaluationException(e);
        }
    }
    if (fd.getProcedure() != null) {
        try {
            return evaluateProcedure(function, tuple, values);
        } catch (TeiidProcessingException e) {
            throw new ExpressionEvaluationException(e);
        }
    }
    // Check for special lookup function
    if (function.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
        if (dataMgr == null) {
            throw new ComponentNotFoundException(QueryPlugin.Event.TEIID30342, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30342));
        }
        String codeTableName = (String) values[0];
        String returnElementName = (String) values[1];
        String keyElementName = (String) values[2];
        try {
            return dataMgr.lookupCodeValue(context, codeTableName, returnElementName, keyElementName, values[3]);
        } catch (TeiidProcessingException e) {
            throw new ExpressionEvaluationException(e);
        }
    }
    // Execute function
    return fd.invokeFunction(values, context, null);
}
Also used : ExpressionEvaluationException(org.teiid.api.exception.query.ExpressionEvaluationException) ComponentNotFoundException(org.teiid.core.ComponentNotFoundException) ExceptionExpression(org.teiid.query.sql.proc.ExceptionExpression) LanguageObject(org.teiid.query.sql.LanguageObject) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) TeiidProcessingException(org.teiid.core.TeiidProcessingException)

Example 2 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.

the class SubqueryAwareEvaluator method evaluatePushdown.

/**
 * Implements must pushdown function handling if supported by the source.
 *
 * The basic strategy is to create a dummy subquery to represent the evaluation
 */
@Override
protected Object evaluatePushdown(Function function, List<?> tuple, Object[] values) throws TeiidComponentException, TeiidProcessingException {
    final FunctionDescriptor fd = function.getFunctionDescriptor();
    if (fd.getMethod() == null) {
        throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
    }
    String schema = null;
    if (fd.getMethod().getParent() == null || !fd.getMethod().getParent().isPhysical()) {
        // find a suitable target
        // TODO: do better than a linear search
        VDBMetaData vdb = this.context.getVdb();
        CapabilitiesFinder capabiltiesFinder = this.context.getQueryProcessorFactory().getCapabiltiesFinder();
        for (ModelMetaData mmd : vdb.getModelMetaDatas().values()) {
            if (!mmd.isSource()) {
                continue;
            }
            SourceCapabilities caps = capabiltiesFinder.findCapabilities(mmd.getName());
            if (caps.supportsCapability(Capability.SELECT_WITHOUT_FROM) && caps.supportsFunction(fd.getMethod().getFullName())) {
                schema = mmd.getName();
                break;
            }
        }
        if (schema == null) {
            throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
        }
    } else {
        if (!CapabilitiesUtil.supports(Capability.SELECT_WITHOUT_FROM, fd.getMethod().getParent(), context.getMetadata(), context.getQueryProcessorFactory().getCapabiltiesFinder())) {
            if (elements != null) {
                Integer index = (Integer) elements.get(function);
                if (index != null) {
                    return tuple.get(index.intValue());
                }
            }
            throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getFullName()));
        }
        schema = fd.getSchema();
    }
    ScalarSubquery ss = null;
    if (functionState != null) {
        ss = functionState.get(function);
    }
    Expression[] functionArgs = new Expression[values.length];
    for (int i = 0; i < values.length; i++) {
        functionArgs[i] = new Constant(values[i]);
    }
    if (ss == null) {
        final Query command = new Query();
        Select select = new Select();
        command.setSelect(select);
        Function f = new Function(function.getName(), functionArgs);
        f.setType(function.getType());
        f.setFunctionDescriptor(fd);
        select.addSymbol(f);
        ss = new ScalarSubquery(command);
        SymbolMap correlatedReferences = new SymbolMap();
        Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(function, true);
        if (!elements.isEmpty()) {
            for (ElementSymbol es : elements) {
                correlatedReferences.addMapping(es, es);
            }
            command.setCorrelatedReferences(correlatedReferences);
        }
        command.setProcessorPlan(new SimpleProcessorPlan(command, schema, fd, Arrays.asList(new Constant(null, fd.getReturnType()))));
    } else {
        ((Function) ((ExpressionSymbol) ss.getCommand().getProjectedSymbols().get(0)).getExpression()).setArgs(functionArgs);
    }
    if (functionState == null) {
        this.functionState = new HashMap<Function, ScalarSubquery>(2);
    }
    functionState.put(function, ss);
    return internalEvaluate(ss, tuple);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ScalarSubquery(org.teiid.query.sql.symbol.ScalarSubquery) Query(org.teiid.query.sql.lang.Query) Constant(org.teiid.query.sql.symbol.Constant) SymbolMap(org.teiid.query.sql.util.SymbolMap) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) ModelMetaData(org.teiid.adminapi.impl.ModelMetaData) Function(org.teiid.query.sql.symbol.Function) CapabilitiesFinder(org.teiid.query.optimizer.capabilities.CapabilitiesFinder) FunctionExecutionException(org.teiid.api.exception.query.FunctionExecutionException) Expression(org.teiid.query.sql.symbol.Expression) VDBMetaData(org.teiid.adminapi.impl.VDBMetaData) Select(org.teiid.query.sql.lang.Select) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities)

Example 3 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.

the class LanguageBridgeFactory method translate.

org.teiid.language.Expression translate(Function function) {
    Expression[] args = function.getArgs();
    List<org.teiid.language.Expression> params = new ArrayList<org.teiid.language.Expression>(args.length);
    for (int i = 0; i < args.length; i++) {
        params.add(translate(args[i]));
    }
    String name = function.getName();
    if (function.getFunctionDescriptor() != null) {
        name = function.getFunctionDescriptor().getName();
        if (!supportsConcat2 && function.getFunctionDescriptor().getMethod().getParent() == null && name.equalsIgnoreCase(SourceSystemFunctions.CONCAT2)) {
            Expression[] newArgs = new Expression[args.length];
            boolean useCase = true;
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof Constant) {
                    newArgs[i] = args[i];
                    useCase = false;
                } else {
                    // $NON-NLS-1$
                    Function f = new Function(SourceSystemFunctions.IFNULL, new Expression[] { args[i], new Constant("") });
                    newArgs[i] = f;
                    f.setType(args[i].getType());
                    FunctionDescriptor descriptor = metadataFactory.getMetadata().getFunctionLibrary().findFunction(SourceSystemFunctions.IFNULL, new Class[] { args[i].getType(), DataTypeManager.DefaultDataClasses.STRING });
                    f.setFunctionDescriptor(descriptor);
                }
            }
            Function concat = new Function(SourceSystemFunctions.CONCAT, newArgs);
            concat.setType(DataTypeManager.DefaultDataClasses.STRING);
            if (!useCase) {
                return translate(concat);
            }
            FunctionDescriptor descriptor = metadataFactory.getMetadata().getFunctionLibrary().findFunction(SourceSystemFunctions.CONCAT, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
            concat.setFunctionDescriptor(descriptor);
            List<CompoundCriteria> when = Arrays.asList(new CompoundCriteria(CompoundCriteria.AND, new IsNullCriteria(args[0]), new IsNullCriteria(args[1])));
            Constant nullConstant = new Constant(null, DataTypeManager.DefaultDataClasses.STRING);
            List<Constant> then = Arrays.asList(nullConstant);
            SearchedCaseExpression caseExpr = new SearchedCaseExpression(when, then);
            caseExpr.setElseExpression(concat);
            caseExpr.setType(DataTypeManager.DefaultDataClasses.STRING);
            return translate(caseExpr);
        }
        // check for translator pushdown functions, and use the name in source if possible
        if (function.getFunctionDescriptor().getMethod().getNameInSource() != null && (CoreConstants.SYSTEM_MODEL.equals(function.getFunctionDescriptor().getSchema()) || (function.getFunctionDescriptor().getMethod().getParent() != null && function.getFunctionDescriptor().getMethod().getParent().isPhysical()))) {
            name = function.getFunctionDescriptor().getMethod().getNameInSource();
        }
    } else {
        name = Symbol.getShortName(name);
    }
    // if there is any ambiguity in the function name it will be up to the translator logic to check the
    // metadata
    org.teiid.language.Function result = new org.teiid.language.Function(name, params, function.getType());
    if (function.getFunctionDescriptor() != null) {
        result.setMetadataObject(function.getFunctionDescriptor().getMethod());
    }
    return result;
}
Also used : Constant(org.teiid.query.sql.symbol.Constant) org.teiid.language(org.teiid.language) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) WindowFunction(org.teiid.query.sql.symbol.WindowFunction) Function(org.teiid.query.sql.symbol.Function) SearchedCaseExpression(org.teiid.query.sql.symbol.SearchedCaseExpression) SearchedCaseExpression(org.teiid.query.sql.symbol.SearchedCaseExpression) Expression(org.teiid.query.sql.symbol.Expression)

Example 4 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.

the class TestExpressionEvaluator method testFunction1.

@Test
public void testFunction1() {
    // $NON-NLS-1$
    ElementSymbol e1 = new ElementSymbol("e1");
    e1.setType(String.class);
    // $NON-NLS-1$
    ElementSymbol e2 = new ElementSymbol("e2");
    e2.setType(String.class);
    // $NON-NLS-1$
    Function func = new Function("concat", new Expression[] { e1, e2 });
    // $NON-NLS-1$
    FunctionDescriptor desc = RealMetadataFactory.SFM.getSystemFunctionLibrary().findFunction("concat", new Class[] { String.class, String.class });
    func.setFunctionDescriptor(desc);
    Expression[] elements = new Expression[] { e1, e2 };
    Object[] values = new Object[] { // $NON-NLS-1$ //$NON-NLS-2$
    "xyz", // $NON-NLS-1$ //$NON-NLS-2$
    "abc" };
    // $NON-NLS-1$
    helpTestEval(func, elements, values, null, null, "xyzabc");
}
Also used : FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) Test(org.junit.Test)

Example 5 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.

the class TestExpressionEvaluator method helpTestCommandPayload.

public void helpTestCommandPayload(Serializable payload, String property, String expectedValue) throws Exception {
    // $NON-NLS-1$
    Function func = new Function("commandpayload", new Expression[] {});
    Class[] parameterSignature = null;
    if (property == null) {
        parameterSignature = new Class[] {};
    } else {
        parameterSignature = new Class[] { String.class };
    }
    // $NON-NLS-1$
    FunctionDescriptor desc = RealMetadataFactory.SFM.getSystemFunctionLibrary().findFunction("commandpayload", parameterSignature);
    func.setFunctionDescriptor(desc);
    FakeDataManager dataMgr = new FakeDataManager();
    // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    CommandContext context = new CommandContext(null, "user", payload, "vdb", 1, false);
    if (property != null) {
        func.setArgs(new Expression[] { new Constant(property) });
    }
    String actual = (String) new Evaluator(Collections.emptyMap(), dataMgr, context).evaluate(func, Collections.emptyList());
    assertEquals(expectedValue, actual);
}
Also used : CommandContext(org.teiid.query.util.CommandContext) FakeDataManager(org.teiid.query.processor.FakeDataManager) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) Evaluator(org.teiid.query.eval.Evaluator)

Aggregations

FunctionDescriptor (org.teiid.query.function.FunctionDescriptor)27 Test (org.junit.Test)11 Constant (org.teiid.query.sql.symbol.Constant)11 Function (org.teiid.query.sql.symbol.Function)11 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)9 ArrayList (java.util.ArrayList)7 FunctionLibrary (org.teiid.query.function.FunctionLibrary)7 List (java.util.List)6 FakeDataManager (org.teiid.query.processor.FakeDataManager)6 LanguageObject (org.teiid.query.sql.LanguageObject)5 Expression (org.teiid.query.sql.symbol.Expression)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 FunctionExecutionException (org.teiid.api.exception.query.FunctionExecutionException)3 BlockedException (org.teiid.common.buffer.BlockedException)3 ExpressionSymbol (org.teiid.query.sql.symbol.ExpressionSymbol)3 QueryResolverException (org.teiid.api.exception.query.QueryResolverException)2 TeiidComponentException (org.teiid.core.TeiidComponentException)2 TeiidProcessingException (org.teiid.core.TeiidProcessingException)2 Evaluator (org.teiid.query.eval.Evaluator)2