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);
}
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);
}
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;
}
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");
}
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);
}
Aggregations