Search in sources :

Example 16 with FunctionDescriptor

use of org.teiid.query.function.FunctionDescriptor 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());
    }
}
Also used : FunctionLibrary(org.teiid.query.function.FunctionLibrary) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) UpdateInfo(org.teiid.query.validator.UpdateValidator.UpdateInfo) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 17 with FunctionDescriptor

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

the class RuleCollapseSource method execute.

public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    for (PlanNode accessNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.ACCESS)) {
        // Get nested non-relational plan if there is one
        ProcessorPlan nonRelationalPlan = FrameUtil.getNestedPlan(accessNode);
        Command command = FrameUtil.getNonQueryCommand(accessNode);
        if (nonRelationalPlan != null) {
            accessNode.setProperty(NodeConstants.Info.PROCESSOR_PLAN, nonRelationalPlan);
        } else if (RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata) == null) {
        // with query or processor plan already set
        } else if (command == null) {
            PlanNode commandRoot = accessNode;
            GroupSymbol intoGroup = (GroupSymbol) accessNode.getFirstChild().getProperty(NodeConstants.Info.INTO_GROUP);
            Set<Object> toCheck = (Set<Object>) commandRoot.getProperty(NodeConstants.Info.CHECK_MAT_VIEW);
            if (intoGroup != null) {
                commandRoot = NodeEditor.findNodePreOrder(accessNode, NodeConstants.Types.SOURCE).getFirstChild();
            } else {
                plan = removeUnnecessaryInlineView(plan, commandRoot);
            }
            QueryCommand queryCommand = createQuery(context, capFinder, accessNode, commandRoot);
            if (toCheck != null) {
                modifyToCheckMatViewStatus(metadata, queryCommand, toCheck);
            }
            Object modelId = RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata);
            if (queryCommand instanceof Query && CapabilitiesUtil.supports(Capability.PARTIAL_FILTERS, modelId, metadata, capFinder)) {
                // this logic relies on the capability restrictions made in capabilities converter
                Query query = (Query) queryCommand;
                if (query.getCriteria() != null) {
                    List<Criteria> toFilter = new ArrayList<Criteria>();
                    HashSet<ElementSymbol> select = new LinkedHashSet(query.getSelect().getProjectedSymbols());
                    outer: for (Criteria crit : Criteria.separateCriteriaByAnd(query.getCriteria())) {
                        for (ElementSymbol es : ElementCollectorVisitor.getElements(crit, true)) {
                            if (Boolean.valueOf(metadata.getExtensionProperty(es.getMetadataID(), PARTIAL_PROPERTY, false)) && select.contains(es)) {
                                toFilter.add((Criteria) crit.clone());
                                continue outer;
                            }
                        }
                    }
                    if (!toFilter.isEmpty()) {
                        PlanNode postFilter = RelationalPlanner.createSelectNode(CompoundCriteria.combineCriteria(toFilter), false);
                        ElementCollectorVisitor.getElements(toFilter, select);
                        postFilter.setProperty(Info.OUTPUT_COLS, new ArrayList<Expression>(query.getSelect().getProjectedSymbols()));
                        if (accessNode.getParent() != null) {
                            accessNode.addAsParent(postFilter);
                        } else {
                            plan = postFilter;
                            postFilter.addFirstChild(accessNode);
                        }
                        if (select.size() != query.getSelect().getProjectedSymbols().size()) {
                            // correct projection
                            query.getSelect().setSymbols(select);
                            accessNode.setProperty(Info.OUTPUT_COLS, new ArrayList<Expression>(select));
                        }
                    }
                }
            }
            // find all pushdown functions in evaluatable locations and mark them to be evaluated by the source
            LanguageVisitor lv = new LanguageVisitor() {

                @Override
                public void visit(Function f) {
                    FunctionDescriptor fd = f.getFunctionDescriptor();
                    if (f.isEval()) {
                        try {
                            if (modelId != null && fd.getPushdown() == PushDown.MUST_PUSHDOWN && fd.getMethod() != null && CapabilitiesUtil.isSameConnector(modelId, fd.getMethod().getParent(), metadata, capFinder)) {
                                f.setEval(false);
                            } else if (fd.getDeterministic() == Determinism.NONDETERMINISTIC && CapabilitiesUtil.supportsScalarFunction(modelId, f, metadata, capFinder)) {
                                f.setEval(false);
                            }
                        } catch (QueryMetadataException e) {
                            throw new TeiidRuntimeException(e);
                        } catch (TeiidComponentException e) {
                            throw new TeiidRuntimeException(e);
                        }
                    }
                }

                @Override
                public void visit(SubqueryFromClause obj) {
                    PreOrPostOrderNavigator.doVisit(obj.getCommand(), this, true);
                }

                @Override
                public void visit(WithQueryCommand obj) {
                    PreOrPostOrderNavigator.doVisit(obj.getCommand(), this, true);
                }
            };
            PreOrPostOrderNavigator.doVisit(queryCommand, lv, true);
            plan = addDistinct(metadata, capFinder, accessNode, plan, queryCommand, capFinder);
            command = queryCommand;
            queryCommand.setSourceHint((SourceHint) accessNode.getProperty(Info.SOURCE_HINT));
            queryCommand.getProjectedQuery().setSourceHint((SourceHint) accessNode.getProperty(Info.SOURCE_HINT));
            if (intoGroup != null) {
                Insert insertCommand = (Insert) commandRoot.getParent().getProperty(NodeConstants.Info.VIRTUAL_COMMAND);
                if (insertCommand == null) {
                    // TODO: this is probably no longer needed as we rewrite select into
                    insertCommand = new Insert(intoGroup, ResolverUtil.resolveElementsInGroup(intoGroup, metadata), null);
                }
                insertCommand.setQueryExpression(queryCommand);
                command = insertCommand;
            }
        }
        if (command != null) {
            accessNode.setProperty(NodeConstants.Info.ATOMIC_REQUEST, command);
        }
        accessNode.removeAllChildren();
    }
    return plan;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) TeiidRuntimeException(org.teiid.core.TeiidRuntimeException) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) LanguageVisitor(org.teiid.query.sql.LanguageVisitor) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) TeiidComponentException(org.teiid.core.TeiidComponentException) ProcessorPlan(org.teiid.query.processor.ProcessorPlan)

Example 18 with FunctionDescriptor

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

the class RuleCollapseSource method modifyToCheckMatViewStatus.

private void modifyToCheckMatViewStatus(QueryMetadataInterface metadata, QueryCommand queryCommand, Set<Object> ids) throws QueryMetadataException, TeiidComponentException {
    for (Object viewMatadataId : ids) {
        String schemaName = metadata.getName(metadata.getModelID(viewMatadataId));
        String viewName = metadata.getName(viewMatadataId);
        Expression expr1 = new Constant(schemaName);
        Expression expr2 = new Constant(viewName);
        // $NON-NLS-1$
        Function status = new Function("mvstatus", new Expression[] { expr1, expr2 });
        status.setType(DataTypeManager.DefaultDataClasses.INTEGER);
        FunctionDescriptor descriptor = // $NON-NLS-1$
        metadata.getFunctionLibrary().findFunction("mvstatus", new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
        status.setFunctionDescriptor(descriptor);
        Query query = queryCommand.getProjectedQuery();
        // insert first so that it gets evaluated ahead of any false predicate
        query.setCriteria(Criteria.combineCriteria(new CompareCriteria(status, CompareCriteria.EQ, new Constant(1)), query.getCriteria()));
    }
}
Also used : FunctionDescriptor(org.teiid.query.function.FunctionDescriptor)

Example 19 with FunctionDescriptor

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

the class ResolverVisitor method findWithImplicitConversions.

/**
 * Find possible matches based on implicit conversions of the arguments.
 * NOTE: This method has the side-effect of explicitly inserting conversions into the function arguments,
 * and thereby changing the structure of the function call.
 * @param library
 * @param function
 * @param types
 * @return
 * @throws TeiidComponentException
 * @throws InvalidFunctionException
 * @since 4.3
 */
private List<FunctionDescriptor> findWithImplicitConversions(FunctionLibrary library, Function function, Expression[] args, Class<?>[] types, boolean hasArgWithoutType) throws QueryResolverException, TeiidComponentException, InvalidFunctionException {
    // Try to find implicit conversion path to still perform this function
    ConversionResult cr = library.determineNecessaryConversions(function.getName(), function.getType(), args, types, hasArgWithoutType);
    if (cr.method == null) {
        return Collections.emptyList();
    }
    Class<?>[] newSignature = types;
    if (cr.needsConverion) {
        FunctionDescriptor[] conversions = library.getConverts(cr.method, types);
        newSignature = new Class[conversions.length];
        // Insert new conversion functions as necessary, while building new signature
        for (int i = 0; i < conversions.length; i++) {
            Class<?> newType = types[i];
            if (conversions[i] != null) {
                newType = conversions[i].getReturnType();
                setDesiredType(args[i], newType, function);
                // only currently typed expressions need conversions
                if (types[i] != null && newType != DataTypeManager.DefaultDataClasses.OBJECT) {
                    // directly resolve constants
                    if (args[i] instanceof Constant && newType == DataTypeManager.DefaultDataClasses.TIMESTAMP) {
                        args[i] = ResolverUtil.getProperlyTypedConstant(((Constant) args[i]).getValue(), newType);
                    } else {
                        function.insertConversion(i, conversions[i]);
                    }
                }
            }
            newSignature[i] = newType;
        }
    }
    String name = cr.method.getFullName();
    // Now resolve using the new signature to get the function's descriptor
    return library.findAllFunctions(name, newSignature);
}
Also used : ConversionResult(org.teiid.query.function.FunctionLibrary.ConversionResult) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor)

Example 20 with FunctionDescriptor

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

the class ResolverVisitor method resolveFunction.

/**
 * Resolve function such that all functions are resolved and type-safe.
 */
void resolveFunction(Function function, FunctionLibrary library) throws QueryResolverException, TeiidComponentException {
    // Check whether this function is already resolved
    if (function.getFunctionDescriptor() != null) {
        return;
    }
    // Look up types for all args
    boolean hasArgWithoutType = false;
    Expression[] args = function.getArgs();
    Class<?>[] types = new Class[args.length];
    for (int i = 0; i < args.length; i++) {
        types[i] = args[i].getType();
        if (types[i] == null) {
            if (!(args[i] instanceof Reference)) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID30067, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30067, new Object[] { args[i], function }));
            }
            hasArgWithoutType = true;
        }
    }
    // special case handling for convert of an untyped reference
    if (FunctionLibrary.isConvert(function) && hasArgWithoutType) {
        Constant constant = (Constant) function.getArg(1);
        Class<?> type = metadata.getDataTypeClass((String) constant.getValue());
        setDesiredType(function.getArg(0), type, function);
        types[0] = type;
        hasArgWithoutType = false;
    }
    // Attempt to get exact match of function for this signature
    List<FunctionDescriptor> fds;
    try {
        fds = findWithImplicitConversions(library, function, args, types, hasArgWithoutType);
        if (fds.isEmpty()) {
            if (!library.hasFunctionMethod(function.getName(), args.length)) {
                // Unknown function form
                throw new QueryResolverException(QueryPlugin.Event.TEIID30068, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30068, function));
            }
            // Known function form - but without type information
            if (hasArgWithoutType) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID30069, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30069, function));
            }
            // Known function form - unable to find implicit conversions
            throw new QueryResolverException(QueryPlugin.Event.TEIID30070, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30070, function));
        }
        if (fds.size() > 1) {
            throw new QueryResolverException(QueryPlugin.Event.TEIID31150, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31150, function));
        }
    } catch (InvalidFunctionException e) {
        // Known function form - but without type information
        if (hasArgWithoutType) {
            throw new QueryResolverException(QueryPlugin.Event.TEIID30069, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30069, function));
        }
        throw new QueryResolverException(QueryPlugin.Event.TEIID31150, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31150, function));
    }
    FunctionDescriptor fd = fds.get(0);
    if (fd.getMethod().isVarArgs() && fd.getTypes().length == types.length && library.isVarArgArrayParam(fd.getMethod(), types, types.length - 1, fd.getTypes()[types.length - 1])) {
        fd = fd.clone();
        fd.setCalledWithVarArgArrayParam(true);
    }
    if (fd.isSystemFunction(FunctionLibrary.CONVERT) || fd.isSystemFunction(FunctionLibrary.CAST)) {
        String dataType = (String) ((Constant) args[1]).getValue();
        Class<?> dataTypeClass = metadata.getDataTypeClass(dataType);
        fd = library.findTypedConversionFunction(args[0].getType(), dataTypeClass);
        // Verify that the type conversion from src to type is even valid
        Class<?> srcTypeClass = args[0].getType();
        if (srcTypeClass != null && dataTypeClass != null && !srcTypeClass.equals(dataTypeClass) && !DataTypeManager.isTransformable(srcTypeClass, dataTypeClass)) {
            throw new QueryResolverException(QueryPlugin.Event.TEIID30071, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30071, new Object[] { DataTypeManager.getDataTypeName(srcTypeClass), dataType }));
        }
    } else if (fd.isSystemFunction(FunctionLibrary.LOOKUP)) {
        ResolverUtil.ResolvedLookup lookup = ResolverUtil.resolveLookup(function, metadata);
        fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType());
    } else if (fd.isSystemFunction(FunctionLibrary.ARRAY_GET)) {
        if (args[0].getType() != null && args[0].getType().isArray()) {
            fd = library.copyFunctionChangeReturnType(fd, args[0].getType().getComponentType());
        } else {
            if (function.getType() != null) {
                setDesiredType(args[0], function.getType(), function);
            }
            if (args[0].getType() != DataTypeManager.DefaultDataClasses.OBJECT) {
                throw new QueryResolverException(QueryPlugin.Event.TEIID31145, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31145, DataTypeManager.getDataTypeName(args[0].getType()), function));
            }
        }
    } else if (Boolean.valueOf(fd.getMethod().getProperty(TEIID_PASS_THROUGH_TYPE, false))) {
        // hack largely to support pg
        fd = library.copyFunctionChangeReturnType(fd, args[0].getType());
    }
    function.setFunctionDescriptor(fd);
    function.setType(fd.getReturnType());
    if (CoreConstants.SYSTEM_MODEL.equals(fd.getSchema())) {
        if (StringUtil.startsWithIgnoreCase(function.getName(), SYS_PREFIX)) {
            function.setName(function.getName().substring(SYS_PREFIX.length()));
        }
    } else if (library.getSystemFunctions().hasFunctionWithName(function.getName()) && !StringUtil.startsWithIgnoreCase(function.getName(), function.getFunctionDescriptor().getSchema() + ElementSymbol.SEPARATOR)) {
        function.setName(function.getFunctionDescriptor().getSchema() + ElementSymbol.SEPARATOR + function.getName());
    }
}
Also used : FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) QueryResolverException(org.teiid.api.exception.query.QueryResolverException) ExceptionExpression(org.teiid.query.sql.proc.ExceptionExpression) LanguageObject(org.teiid.query.sql.LanguageObject) InvalidFunctionException(org.teiid.api.exception.query.InvalidFunctionException)

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