use of org.teiid.query.function.FunctionLibrary 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.FunctionLibrary 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;
}
use of org.teiid.query.function.FunctionLibrary in project teiid by teiid.
the class RelationalPlanner method buildTree.
/**
* Build a join plan based on the structure in a clause. These structures should be
* essentially the same tree, but with different objects and details.
* @param clause Clause to build tree from
* @param parent Parent node to attach join node structure to
* @param sourceMap Map of group to source node, used for connecting children to join plan
* @param markJoinsInternal Flag saying whether joins built in this method should be marked
* as internal
* @throws TeiidComponentException
* @throws QueryMetadataException
* @throws TeiidProcessingException
*/
void buildTree(FromClause clause, final PlanNode parent) throws QueryMetadataException, TeiidComponentException, TeiidProcessingException {
PlanNode node = null;
if (clause instanceof UnaryFromClause) {
// No join required
UnaryFromClause ufc = (UnaryFromClause) clause;
GroupSymbol group = ufc.getGroup();
if (metadata.isVirtualGroup(group.getMetadataID()) && !group.isTempGroupSymbol()) {
hints.hasVirtualGroups = true;
}
if (!hints.hasRowBasedSecurity && RowBasedSecurityHelper.applyRowSecurity(metadata, group, context)) {
hints.hasRowBasedSecurity = true;
}
if (metadata.getFunctionBasedExpressions(group.getMetadataID()) != null) {
hints.hasFunctionBasedColumns = true;
}
boolean planningStackEntry = true;
Command nestedCommand = ufc.getExpandedCommand();
if (nestedCommand != null) {
// other paths are inlining, so there isn't a proper virtual layer
if (!group.isProcedure()) {
planningStackEntry = false;
hints.hasVirtualGroups = true;
}
} else if (!group.isProcedure()) {
Object id = getTrackableGroup(group, metadata);
if (id != null) {
context.accessedPlanningObject(id);
}
if (!group.isTempGroupSymbol() && metadata.isVirtualGroup(group.getMetadataID())) {
nestedCommand = resolveVirtualGroup(group);
}
}
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
if (ufc.isNoUnnest()) {
node.setProperty(Info.NO_UNNEST, Boolean.TRUE);
}
node.addGroup(group);
if (nestedCommand != null) {
UpdateInfo info = ProcedureContainerResolver.getUpdateInfo(group, metadata);
if (info != null && info.getPartitionInfo() != null && !info.getPartitionInfo().isEmpty()) {
Map<ElementSymbol, List<Set<Constant>>> partitionInfo = info.getPartitionInfo();
if (group.getDefinition() != null) {
partitionInfo = remapPartitionInfo(group, partitionInfo);
}
node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
}
SourceHint previous = this.sourceHint;
if (nestedCommand.getSourceHint() != null) {
this.sourceHint = SourceHint.combine(previous, nestedCommand.getSourceHint());
}
addNestedCommand(node, group, nestedCommand, nestedCommand, true, planningStackEntry);
this.sourceHint = previous;
} else if (this.sourceHint != null) {
node.setProperty(Info.SOURCE_HINT, this.sourceHint);
}
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
parent.addLastChild(node);
} else if (clause instanceof JoinPredicate) {
JoinPredicate jp = (JoinPredicate) clause;
// Set up new join node corresponding to this join predicate
node = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
node.setProperty(NodeConstants.Info.JOIN_TYPE, jp.getJoinType());
node.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
node.setProperty(NodeConstants.Info.JOIN_CRITERIA, jp.getJoinCriteria());
if (jp.isPreserve()) {
node.setProperty(Info.PRESERVE, Boolean.TRUE);
}
// Attach join node to parent
parent.addLastChild(node);
// Handle each child
FromClause[] clauses = new FromClause[] { jp.getLeftClause(), jp.getRightClause() };
for (int i = 0; i < 2; i++) {
if (jp.isPreserve() && clauses[i] instanceof JoinPredicate) {
((JoinPredicate) clauses[i]).setPreserve(true);
}
buildTree(clauses[i], node);
// Add groups to joinNode
node.addGroups(node.getLastChild().getGroups());
}
} else if (clause instanceof SubqueryFromClause) {
SubqueryFromClause sfc = (SubqueryFromClause) clause;
GroupSymbol group = sfc.getGroupSymbol();
Command nestedCommand = sfc.getCommand();
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
if (sfc.isLateral()) {
sfc.getCommand().setCorrelatedReferences(getCorrelatedReferences(parent, node, sfc));
}
if (sfc.isNoUnnest()) {
node.setProperty(Info.NO_UNNEST, Boolean.TRUE);
}
SourceHint previous = this.sourceHint;
if (nestedCommand.getSourceHint() != null) {
this.sourceHint = SourceHint.combine(previous, nestedCommand.getSourceHint());
}
node.addGroup(group);
addNestedCommand(node, group, nestedCommand, nestedCommand, true, false);
this.sourceHint = previous;
if (nestedCommand instanceof SetQuery) {
Map<ElementSymbol, List<Set<Constant>>> partitionInfo = PartitionAnalyzer.extractPartionInfo((SetQuery) nestedCommand, ResolverUtil.resolveElementsInGroup(group, metadata));
if (!partitionInfo.isEmpty()) {
node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
}
}
hints.hasVirtualGroups = true;
parent.addLastChild(node);
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
} else if (clause instanceof TableFunctionReference) {
TableFunctionReference tt = (TableFunctionReference) clause;
GroupSymbol group = tt.getGroupSymbol();
if (group.getName().contains(RulePlaceAccess.RECONTEXT_STRING)) {
this.context.getGroups().add(group.getName());
}
// special handling to convert array table into a mergable construct
if (parent.getType() == NodeConstants.Types.JOIN && tt instanceof ArrayTable) {
JoinType jt = (JoinType) parent.getProperty(Info.JOIN_TYPE);
if (jt != JoinType.JOIN_FULL_OUTER && parent.getChildCount() > 0) {
ArrayTable at = (ArrayTable) tt;
// rewrite if free of subqueries
if (ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(at).isEmpty()) {
List<ElementSymbol> symbols = at.getProjectedSymbols();
FunctionLibrary funcLib = this.metadata.getFunctionLibrary();
FunctionDescriptor descriptor = funcLib.findFunction(FunctionLibrary.ARRAY_GET, new Class[] { DataTypeManager.DefaultDataClasses.OBJECT, DataTypeManager.DefaultDataClasses.INTEGER });
Query query = new Query();
Select select = new Select();
query.setSelect(select);
for (int i = 0; i < symbols.size(); i++) {
ElementSymbol es = symbols.get(i);
Function f = new Function(FunctionLibrary.ARRAY_GET, new Expression[] { (Expression) at.getArrayValue().clone(), new Constant(i + 1) });
f.setType(DataTypeManager.DefaultDataClasses.OBJECT);
f.setFunctionDescriptor(descriptor);
Expression ex = f;
if (es.getType() != DataTypeManager.DefaultDataClasses.OBJECT) {
ex = ResolverUtil.getConversion(ex, DataTypeManager.DefaultDataTypes.OBJECT, DataTypeManager.getDataTypeName(es.getType()), false, metadata.getFunctionLibrary());
}
select.addSymbol(new AliasSymbol(es.getShortName(), ex));
}
SubqueryFromClause sfc = new SubqueryFromClause(at.getGroupSymbol(), query);
sfc.setLateral(true);
buildTree(sfc, parent);
if (!jt.isOuter()) {
// insert is null criteria
IsNullCriteria criteria = new IsNullCriteria((Expression) at.getArrayValue().clone());
if (sfc.getCommand().getCorrelatedReferences() != null) {
RuleMergeCriteria.ReferenceReplacementVisitor rrv = new RuleMergeCriteria.ReferenceReplacementVisitor(sfc.getCommand().getCorrelatedReferences());
PreOrPostOrderNavigator.doVisit(criteria, rrv, PreOrPostOrderNavigator.PRE_ORDER);
}
criteria.setNegated(true);
if (jt == JoinType.JOIN_CROSS) {
parent.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER);
}
List<Criteria> joinCriteria = (List<Criteria>) parent.getProperty(Info.JOIN_CRITERIA);
if (joinCriteria == null) {
joinCriteria = new ArrayList<Criteria>(2);
}
joinCriteria.add(criteria);
parent.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria);
}
return;
}
}
}
node = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
node.setProperty(NodeConstants.Info.TABLE_FUNCTION, tt);
tt.setCorrelatedReferences(getCorrelatedReferences(parent, node, tt));
node.addGroup(group);
parent.addLastChild(node);
} else {
// $NON-NLS-1$
throw new AssertionError("Unknown Type");
}
if (clause.isOptional()) {
node.setProperty(NodeConstants.Info.IS_OPTIONAL, Boolean.TRUE);
}
if (clause.getMakeDep() != null) {
node.setProperty(NodeConstants.Info.MAKE_DEP, clause.getMakeDep());
} else if (clause.isMakeNotDep()) {
node.setProperty(NodeConstants.Info.MAKE_NOT_DEP, Boolean.TRUE);
}
if (clause.getMakeInd() != null) {
node.setProperty(NodeConstants.Info.MAKE_IND, clause.getMakeInd());
}
}
use of org.teiid.query.function.FunctionLibrary in project teiid by teiid.
the class QueryRewriter method simplifyParseFormatFunction.
private Criteria simplifyParseFormatFunction(CompareCriteria crit) {
// TODO: this can be relaxed for order preserving operations
if (!(crit.getOperator() == CompareCriteria.EQ || crit.getOperator() == CompareCriteria.NE)) {
return crit;
}
boolean isFormat = false;
Function leftFunction = (Function) crit.getLeftExpression();
String funcName = leftFunction.getName();
String inverseFunction = null;
if (StringUtil.startsWithIgnoreCase(funcName, "parse")) {
// $NON-NLS-1$
String type = funcName.substring(5);
if (!PARSE_FORMAT_TYPES.contains(type)) {
return crit;
}
// $NON-NLS-1$
inverseFunction = "format" + type;
} else if (StringUtil.startsWithIgnoreCase(funcName, "format")) {
// $NON-NLS-1$
String type = funcName.substring(6);
if (!PARSE_FORMAT_TYPES.contains(type)) {
return crit;
}
// $NON-NLS-1$
inverseFunction = "parse" + type;
isFormat = true;
} else {
return crit;
}
Expression rightExpr = crit.getRightExpression();
if (!(rightExpr instanceof Constant)) {
return crit;
}
Expression leftExpr = leftFunction.getArgs()[0];
Expression formatExpr = leftFunction.getArgs()[1];
if (!(formatExpr instanceof Constant)) {
return crit;
}
String format = (String) ((Constant) formatExpr).getValue();
FunctionLibrary funcLib = this.metadata.getFunctionLibrary();
FunctionDescriptor descriptor = funcLib.findFunction(inverseFunction, new Class[] { rightExpr.getType(), formatExpr.getType() });
if (descriptor == null) {
return crit;
}
Object value = ((Constant) rightExpr).getValue();
try {
Object result = descriptor.invokeFunction(new Object[] { context, ((Constant) rightExpr).getValue(), format }, null, this.context);
result = leftFunction.getFunctionDescriptor().invokeFunction(new Object[] { context, result, format }, null, this.context);
if (Constant.COMPARATOR.compare(value, result) != 0) {
return getSimpliedCriteria(crit, leftExpr, crit.getOperator() != CompareCriteria.EQ, true);
}
} catch (FunctionExecutionException e) {
// Not all numeric formats are invertable, so just return the criteria as it may still be valid
return crit;
} catch (BlockedException e) {
return crit;
}
// parseFunctions are all potentially narrowing
if (!isFormat) {
return crit;
}
// TODO: if format is not lossy, then invert the function
return crit;
}
use of org.teiid.query.function.FunctionLibrary in project teiid by teiid.
the class TranslationUtility method addUDF.
public void addUDF(String schema, Collection<FunctionMethod> methods) {
if (methods == null || methods.isEmpty()) {
return;
}
this.functions.add(new FunctionTree(schema, new UDFSource(methods)));
SystemFunctionManager sfm = SystemMetadata.getInstance().getSystemFunctionManager();
functionLibrary = new FunctionLibrary(sfm.getSystemFunctions(), this.functions.toArray(new FunctionTree[this.functions.size()]));
}
Aggregations