use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.
the class TestJoinNode method helpCreateJoin.
protected void helpCreateJoin() {
// $NON-NLS-1$
ElementSymbol es1 = new ElementSymbol("e1");
es1.setType(DataTypeManager.DefaultDataClasses.INTEGER);
// $NON-NLS-1$
ElementSymbol es2 = new ElementSymbol("e2");
es2.setType(DataTypeManager.DefaultDataClasses.INTEGER);
List leftElements = new ArrayList();
leftElements.add(es1);
leftNode = new BlockingFakeRelationalNode(1, leftTuples);
leftNode.setElements(leftElements);
List rightElements = new ArrayList();
rightElements.add(es2);
rightNode = new BlockingFakeRelationalNode(2, rightTuples) {
@Override
public boolean hasBuffer() {
return false;
}
@Override
public TupleBuffer getBufferDirect(int maxRows) throws BlockedException, TeiidComponentException, TeiidProcessingException {
fail();
throw new AssertionError();
}
};
rightNode.setElements(rightElements);
List joinElements = new ArrayList();
joinElements.add(es1);
joinElements.add(es2);
join = new JoinNode(3);
joinStrategy = new NestedLoopJoinStrategy();
join.setJoinStrategy(joinStrategy);
join.setElements(joinElements);
join.setJoinType(joinType);
switch(criteriaType) {
case NO_CRITERIA:
break;
case EQUAL_CRITERIA:
join.setJoinExpressions(Arrays.asList(es1), Arrays.asList(es2));
joinStrategy = new MergeJoinStrategy(SortOption.SORT, SortOption.SORT, false);
join.setJoinStrategy(joinStrategy);
break;
case FUNCTION_CRITERIA:
// $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
Function func = new Function("lookup", new Expression[] { new Constant("pm1.g1"), new Constant("e2"), new Constant("e1"), es1 });
// $NON-NLS-1$
FunctionDescriptor desc = RealMetadataFactory.SFM.getSystemFunctionLibrary().findFunction("lookup", new Class[] { String.class, String.class, String.class, Integer.class });
func.setFunctionDescriptor(desc);
func.setType(DataTypeManager.DefaultDataClasses.INTEGER);
CompareCriteria joinCriteria = new CompareCriteria(es2, CompareCriteria.EQ, func);
join.setJoinCriteria(joinCriteria);
break;
}
}
use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.
the class TestProjectNode method testProjectExpressionFunctionFails.
@Test
public void testProjectExpressionFunctionFails() throws Exception {
// $NON-NLS-1$
ElementSymbol es1 = new ElementSymbol("e1");
es1.setType(DataTypeManager.DefaultDataClasses.STRING);
List elements = new ArrayList();
elements.add(es1);
// $NON-NLS-1$ //$NON-NLS-2$
Function func = new Function("convert", new Expression[] { es1, new Constant("integer") });
// $NON-NLS-1$
FunctionDescriptor fd = RealMetadataFactory.SFM.getSystemFunctionLibrary().findFunction("convert", new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
func.setFunctionDescriptor(fd);
func.setType(DataTypeManager.DefaultDataClasses.INTEGER);
// $NON-NLS-1$
ExpressionSymbol expr = new ExpressionSymbol("expr", func);
List projectElements = new ArrayList();
projectElements.add(expr);
List[] data = new List[] { // $NON-NLS-1$
Arrays.asList(new Object[] { "1" }), // $NON-NLS-1$
Arrays.asList(new Object[] { "2x" }) };
// $NON-NLS-1$
String expectedMessage = "TEIID30328 UNABLE TO EVALUATE CONVERT(E1, INTEGER): TEIID30384 ERROR WHILE EVALUATING FUNCTION CONVERT";
helpTestProjectFails(projectElements, data, elements, expectedMessage);
}
use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.
the class ResolverUtil method getConversion.
/**
* IMPORTANT: source and target must be basic runtime types
* @param sourceExpression
* @param sourceTypeName
* @param targetTypeName
* @param implicit
* @param library
* @return
*/
public static Function getConversion(Expression sourceExpression, String sourceTypeName, String targetTypeName, boolean implicit, FunctionLibrary library) {
Class<?> srcType = DataTypeManager.getDataTypeClass(sourceTypeName);
Class<?> targetType = DataTypeManager.getDataTypeClass(targetTypeName);
try {
setDesiredType(sourceExpression, targetType, sourceExpression);
} catch (QueryResolverException e) {
}
FunctionDescriptor fd = library.findTypedConversionFunction(srcType, DataTypeManager.getDataTypeClass(targetTypeName));
Function conversion = new Function(fd.getName(), new Expression[] { sourceExpression, new Constant(targetTypeName) });
conversion.setType(DataTypeManager.getDataTypeClass(targetTypeName));
conversion.setFunctionDescriptor(fd);
if (implicit) {
conversion.makeImplicit();
}
return conversion;
}
use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.
the class QueryRewriter method rewriteFunction.
private Expression rewriteFunction(Function function) throws TeiidComponentException, TeiidProcessingException {
// rewrite alias functions
String functionName = function.getName();
String actualName = ALIASED_FUNCTIONS.get(functionName);
FunctionLibrary funcLibrary = this.metadata.getFunctionLibrary();
if (actualName != null) {
function.setName(actualName);
Expression[] args = function.getArgs();
Class<?>[] types = new Class[args.length];
for (int i = 0; i < args.length; i++) {
types[i] = args[i].getType();
}
FunctionDescriptor descriptor = funcLibrary.findFunction(actualName, types);
function.setFunctionDescriptor(descriptor);
}
if (StringUtil.startsWithIgnoreCase(functionName, "parse")) {
// $NON-NLS-1$
String type = functionName.substring(5);
if (PARSE_FORMAT_TYPES.contains(type) && Number.class.isAssignableFrom(function.getType()) && !type.equals(DataTypeManager.DefaultDataTypes.BIG_DECIMAL)) {
Function result = new Function(SourceSystemFunctions.PARSEBIGDECIMAL, function.getArgs());
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.PARSEBIGDECIMAL, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
result.setFunctionDescriptor(descriptor);
result.setType(DataTypeManager.DefaultDataClasses.BIG_DECIMAL);
return rewriteFunction(ResolverUtil.getConversion(result, DataTypeManager.DefaultDataTypes.BIG_DECIMAL, DataTypeManager.getDataTypeName(function.getType()), false, metadata.getFunctionLibrary()));
} else if ((DataTypeManager.DefaultDataTypes.DATE.equalsIgnoreCase(type) || DataTypeManager.DefaultDataTypes.TIME.equalsIgnoreCase(type)) && function.getArg(1) instanceof Constant) {
// $NON-NLS-1$
String format = "yyyy-MM-dd";
int length = 10;
if (DataTypeManager.DefaultDataTypes.TIME.equalsIgnoreCase(type)) {
// $NON-NLS-1$
format = "hh:mm:ss";
length = 8;
}
Constant c = (Constant) function.getArg(1);
if (format.equals(c.getValue())) {
Expression arg = function.getArg(0);
if ((arg instanceof Function) && FunctionLibrary.isConvert((Function) arg) && java.util.Date.class.isAssignableFrom(((Function) arg).getArg(0).getType())) {
return rewriteExpressionDirect(ResolverUtil.getConversion(arg, DataTypeManager.DefaultDataTypes.STRING, type, false, metadata.getFunctionLibrary()));
}
}
}
} else if (StringUtil.startsWithIgnoreCase(functionName, "format")) {
// $NON-NLS-1$
String type = functionName.substring(6);
if (PARSE_FORMAT_TYPES.contains(type) && Number.class.isAssignableFrom(function.getArg(0).getType()) && !type.equals(DataTypeManager.DefaultDataTypes.BIG_DECIMAL)) {
Function bigDecimalParam = ResolverUtil.getConversion(function.getArg(0), DataTypeManager.getDataTypeName(function.getArg(0).getType()), DataTypeManager.DefaultDataTypes.BIG_DECIMAL, false, metadata.getFunctionLibrary());
Function result = new Function(SourceSystemFunctions.FORMATBIGDECIMAL, new Expression[] { bigDecimalParam, function.getArg(1) });
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.FORMATBIGDECIMAL, new Class[] { DataTypeManager.DefaultDataClasses.BIG_DECIMAL, DataTypeManager.DefaultDataClasses.STRING });
result.setFunctionDescriptor(descriptor);
result.setType(DataTypeManager.DefaultDataClasses.STRING);
return rewriteFunction(result);
} else if ((DataTypeManager.DefaultDataTypes.DATE.equalsIgnoreCase(type) || DataTypeManager.DefaultDataTypes.TIME.equalsIgnoreCase(type)) && function.getArg(1) instanceof Constant) {
// $NON-NLS-1$
String format = "yyyy-MM-dd";
if (DataTypeManager.DefaultDataTypes.TIME.equalsIgnoreCase(type)) {
// $NON-NLS-1$
format = "hh:mm:ss";
}
Constant c = (Constant) function.getArg(1);
if (format.equals(c.getValue())) {
return rewriteExpressionDirect(ResolverUtil.getConversion(function.getArg(0), DataTypeManager.getDataTypeName(function.getArg(0).getType()), DataTypeManager.DefaultDataTypes.STRING, false, metadata.getFunctionLibrary()));
}
}
}
boolean omitNull = false;
Integer code = FUNCTION_MAP.get(functionName);
if (code != null) {
switch(code) {
case 0:
{
// space(x) => repeat(' ', x)
Function result = new Function(SourceSystemFunctions.REPEAT, // $NON-NLS-1$
new Expression[] { new Constant(" "), function.getArg(0) });
// resolve the function
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.REPEAT, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.INTEGER });
result.setFunctionDescriptor(descriptor);
result.setType(DataTypeManager.DefaultDataClasses.STRING);
function = result;
break;
}
case 1:
{
// TEIID-4455
break;
}
case 2:
{
// rewrite nullif(a, b) => case when (a = b) then null else a
List when = Arrays.asList(new Criteria[] { new CompareCriteria(function.getArg(0), CompareCriteria.EQ, function.getArg(1)) });
Constant nullConstant = new Constant(null, function.getType());
List then = Arrays.asList(new Expression[] { nullConstant });
SearchedCaseExpression caseExpr = new SearchedCaseExpression(when, then);
caseExpr.setElseExpression(function.getArg(0));
caseExpr.setType(function.getType());
return rewriteExpressionDirect(caseExpr);
}
case 3:
{
Expression[] args = function.getArgs();
if (args.length == 2) {
Function result = new Function(SourceSystemFunctions.IFNULL, new Expression[] { function.getArg(0), function.getArg(1) });
// resolve the function
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.IFNULL, new Class[] { function.getType(), function.getType() });
result.setFunctionDescriptor(descriptor);
result.setType(function.getType());
function = result;
}
break;
}
case 4:
omitNull = true;
break;
case 5:
{
if (function.getType() != DataTypeManager.DefaultDataClasses.TIMESTAMP) {
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.TIMESTAMPADD, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.TIMESTAMP });
function.setFunctionDescriptor(descriptor);
Class<?> type = function.getType();
function.setType(DataTypeManager.DefaultDataClasses.TIMESTAMP);
function.getArgs()[2] = ResolverUtil.getConversion(function.getArg(2), DataTypeManager.getDataTypeName(type), DataTypeManager.DefaultDataTypes.TIMESTAMP, false, funcLibrary);
function = ResolverUtil.getConversion(function, DataTypeManager.DefaultDataTypes.TIMESTAMP, DataTypeManager.getDataTypeName(type), false, funcLibrary);
}
break;
}
case 6:
case 7:
{
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.PARSETIMESTAMP, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
function.setName(SourceSystemFunctions.PARSETIMESTAMP);
function.setFunctionDescriptor(descriptor);
Class<?> type = function.getType();
function.setType(DataTypeManager.DefaultDataClasses.TIMESTAMP);
function = ResolverUtil.getConversion(function, DataTypeManager.DefaultDataTypes.TIMESTAMP, DataTypeManager.getDataTypeName(type), false, funcLibrary);
break;
}
case 8:
case 9:
{
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.FORMATTIMESTAMP, new Class[] { DataTypeManager.DefaultDataClasses.TIMESTAMP, DataTypeManager.DefaultDataClasses.STRING });
function.setName(SourceSystemFunctions.FORMATTIMESTAMP);
function.setFunctionDescriptor(descriptor);
function.getArgs()[0] = ResolverUtil.getConversion(function.getArg(0), DataTypeManager.getDataTypeName(function.getArg(0).getType()), DataTypeManager.DefaultDataTypes.TIMESTAMP, false, funcLibrary);
break;
}
case 10:
{
if (new Constant(" ").equals(function.getArg(1))) {
// $NON-NLS-1$
String spec = (String) ((Constant) function.getArg(0)).getValue();
Expression string = function.getArg(2);
if (!SQLConstants.Reserved.TRAILING.equalsIgnoreCase(spec)) {
function = new Function(SourceSystemFunctions.LTRIM, new Expression[] { string });
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.LTRIM, new Class[] { DataTypeManager.DefaultDataClasses.STRING });
function.setFunctionDescriptor(descriptor);
function.setType(DataTypeManager.DefaultDataClasses.STRING);
string = function;
}
if (!SQLConstants.Reserved.LEADING.equalsIgnoreCase(spec)) {
function = new Function(SourceSystemFunctions.RTRIM, new Expression[] { string });
FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.RTRIM, new Class[] { DataTypeManager.DefaultDataClasses.STRING });
function.setFunctionDescriptor(descriptor);
function.setType(DataTypeManager.DefaultDataClasses.STRING);
}
}
break;
}
case 11:
{
if (function.getArg(1) instanceof Constant) {
Constant c = (Constant) function.getArg(1);
if (!c.isMultiValued() && !c.isNull()) {
int val = (Integer) c.getValue();
if (val == 0) {
function.getArgs()[1] = new Constant(1);
}
}
}
break;
}
}
}
Expression[] args = function.getArgs();
Expression[] newArgs = new Expression[args.length];
// Rewrite args
int j = 0;
for (int i = 0; i < args.length; i++) {
Expression ex = rewriteExpressionDirect(args[i]);
if (isNull(ex)) {
if (!function.getFunctionDescriptor().isNullDependent()) {
return new Constant(null, function.getType());
}
if (omitNull) {
continue;
}
}
newArgs[j++] = ex;
}
if (omitNull) {
if (j == 0) {
return new Constant(null, function.getType());
}
if (j == 1) {
return newArgs[0];
}
if (j != args.length) {
newArgs = Arrays.copyOf(newArgs, j);
}
}
function.setArgs(newArgs);
if (FunctionLibrary.isConvert(function)) {
Class<?> srcType = newArgs[0].getType();
Class<?> tgtType = function.getType();
if (srcType != null && tgtType != null && srcType.equals(tgtType)) {
// unnecessary conversion
return newArgs[0];
}
if (function.isImplicit()) {
function.setImplicit(false);
}
if (!(newArgs[0] instanceof Function) || tgtType == DataTypeManager.DefaultDataClasses.OBJECT) {
return function;
}
Function nested = (Function) newArgs[0];
if (!FunctionLibrary.isConvert(nested)) {
return function;
}
Class<?> nestedType = nested.getArgs()[0].getType();
Transform t = DataTypeManager.getTransform(nestedType, nested.getType());
if (t.isExplicit()) {
// explicit conversions are required
return function;
}
if (DataTypeManager.getTransform(nestedType, tgtType) == null) {
// no direct conversion exists
return function;
}
// can't remove a convert that would alter the lexical form
if (tgtType == DataTypeManager.DefaultDataClasses.STRING && (nestedType == DataTypeManager.DefaultDataClasses.BOOLEAN || nestedType == DataTypeManager.DefaultDataClasses.DATE || nestedType == DataTypeManager.DefaultDataClasses.TIME || tgtType == DataTypeManager.DefaultDataClasses.BIG_DECIMAL || tgtType == DataTypeManager.DefaultDataClasses.FLOAT || (tgtType == DataTypeManager.DefaultDataClasses.DOUBLE && srcType != DataTypeManager.DefaultDataClasses.FLOAT))) {
return function;
}
// nested implicit transform is not needed
return rewriteExpressionDirect(ResolverUtil.getConversion(nested.getArgs()[0], DataTypeManager.getDataTypeName(nestedType), DataTypeManager.getDataTypeName(tgtType), false, funcLibrary));
}
// convert DECODESTRING function to CASE expression
if (function.getName().equalsIgnoreCase(FunctionLibrary.DECODESTRING) || function.getName().equalsIgnoreCase(FunctionLibrary.DECODEINTEGER)) {
return convertDecodeFunction(function);
}
return function;
}
use of org.teiid.query.function.FunctionDescriptor in project teiid by teiid.
the class QueryRewriter method simplifyMathematicalCriteria.
/**
* @param criteria
* @return CompareCriteria
*/
private CompareCriteria simplifyMathematicalCriteria(CompareCriteria criteria) throws TeiidProcessingException {
Expression leftExpr = criteria.getLeftExpression();
Expression rightExpr = criteria.getRightExpression();
// Identify all the pieces of this criteria
Function function = (Function) leftExpr;
String funcName = function.getName();
Expression[] args = function.getArgs();
Constant const1 = null;
Expression expr = null;
if (args[1] instanceof Constant) {
const1 = (Constant) args[1];
expr = args[0];
} else {
if (funcName.equals("+") || funcName.equals("*")) {
// $NON-NLS-1$ //$NON-NLS-2$
const1 = (Constant) args[0];
expr = args[1];
} else {
// If we have "5 - x = 10" or "5 / x = 10", abort!
return criteria;
}
}
int operator = criteria.getOperator();
// Determine opposite function
String oppFunc = null;
switch(funcName.charAt(0)) {
// $NON-NLS-1$
case '+':
oppFunc = "-";
break;
// $NON-NLS-1$
case '-':
oppFunc = "+";
break;
// $NON-NLS-1$
case '*':
oppFunc = "/";
break;
// $NON-NLS-1$
case '/':
oppFunc = "*";
break;
}
// Create a function of the two constants and evaluate it
Expression combinedConst = null;
FunctionLibrary funcLib = this.metadata.getFunctionLibrary();
FunctionDescriptor descriptor = funcLib.findFunction(oppFunc, new Class[] { rightExpr.getType(), const1.getType() });
if (descriptor == null) {
// See defect 9380 - this can be caused by const2 being a null Constant, for example (? + 1) < null
return criteria;
}
if (rightExpr instanceof Constant) {
Constant const2 = (Constant) rightExpr;
try {
Object result = descriptor.invokeFunction(new Object[] { const2.getValue(), const1.getValue() }, null, this.context);
combinedConst = new Constant(result, descriptor.getReturnType());
} catch (FunctionExecutionException e) {
throw new QueryValidatorException(QueryPlugin.Event.TEIID30373, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30373, e.getMessage()));
} catch (BlockedException e) {
throw new QueryValidatorException(QueryPlugin.Event.TEIID30373, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30373, e.getMessage()));
}
} else {
Function conversion = new Function(descriptor.getName(), new Expression[] { rightExpr, const1 });
conversion.setType(leftExpr.getType());
conversion.setFunctionDescriptor(descriptor);
combinedConst = conversion;
}
// Flip operator if necessary
if (!(operator == CompareCriteria.EQ || operator == CompareCriteria.NE) && (oppFunc.equals("*") || oppFunc.equals("/"))) {
// $NON-NLS-1$ //$NON-NLS-2$
Object value = const1.getValue();
if (value != null) {
Class type = const1.getType();
Comparable comparisonObject = null;
if (type.equals(DataTypeManager.DefaultDataClasses.INTEGER)) {
comparisonObject = INTEGER_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.DOUBLE)) {
comparisonObject = DOUBLE_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.FLOAT)) {
comparisonObject = FLOAT_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.LONG)) {
comparisonObject = LONG_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.BIG_INTEGER)) {
comparisonObject = BIG_INTEGER_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.BIG_DECIMAL)) {
comparisonObject = BIG_DECIMAL_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.SHORT)) {
comparisonObject = SHORT_ZERO;
} else if (type.equals(DataTypeManager.DefaultDataClasses.BYTE)) {
comparisonObject = BYTE_ZERO;
} else {
// Unknown type
return criteria;
}
// then need to switch operator.
if (comparisonObject.compareTo(value) > 0) {
switch(operator) {
case CompareCriteria.LE:
operator = CompareCriteria.GE;
break;
case CompareCriteria.LT:
operator = CompareCriteria.GT;
break;
case CompareCriteria.GE:
operator = CompareCriteria.LE;
break;
case CompareCriteria.GT:
operator = CompareCriteria.LT;
break;
}
}
}
}
criteria.setLeftExpression(expr);
criteria.setRightExpression(combinedConst);
criteria.setOperator(operator);
// Return new simplified criteria
return criteria;
}
Aggregations