Search in sources :

Example 6 with UpdateInfo

use of org.teiid.query.validator.UpdateValidator.UpdateInfo 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 7 with UpdateInfo

use of org.teiid.query.validator.UpdateValidator.UpdateInfo in project teiid by teiid.

the class QueryRewriter method rewriteInsert.

private Command rewriteInsert(Insert insert) throws TeiidComponentException, TeiidProcessingException {
    Command c = rewriteInsertForWriteThrough(insert);
    if (c != null) {
        return c;
    }
    UpdateInfo info = insert.getUpdateInfo();
    if (info != null && info.isInherentInsert()) {
        // TODO: update error messages
        UpdateMapping mapping = info.findInsertUpdateMapping(insert, true);
        if (mapping == null) {
            throw new QueryValidatorException(QueryPlugin.Event.TEIID30375, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30375, insert.getVariables()));
        }
        Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
        List<ElementSymbol> mappedSymbols = new ArrayList<ElementSymbol>(insert.getVariables().size());
        for (ElementSymbol symbol : insert.getVariables()) {
            mappedSymbols.add(symbolMap.get(symbol));
        }
        insert.setVariables(mappedSymbols);
        insert.setGroup(mapping.getGroup().clone());
        insert.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(insert.getGroup(), metadata, Command.TYPE_INSERT, true));
        return rewriteInsert(insert);
    }
    if (insert.getQueryExpression() != null) {
        insert.setQueryExpression((QueryCommand) rewriteCommand(insert.getQueryExpression(), true));
        return correctDatatypes(insert);
    }
    // Evaluate any function / constant trees in the insert values
    List expressions = insert.getValues();
    List evalExpressions = new ArrayList(expressions.size());
    Iterator expIter = expressions.iterator();
    boolean preserveUnknownOld = preserveUnknown;
    preserveUnknown = true;
    while (expIter.hasNext()) {
        Expression exp = (Expression) expIter.next();
        if (processing && exp instanceof ExpressionSymbol) {
            // expression symbols that were created in the PlanToProcessesConverter
            evalExpressions.add(evaluate(exp, true));
        } else {
            evalExpressions.add(rewriteExpressionDirect(exp));
        }
    }
    preserveUnknown = preserveUnknownOld;
    insert.setValues(evalExpressions);
    return insert;
}
Also used : UpdateMapping(org.teiid.query.validator.UpdateValidator.UpdateMapping) QueryValidatorException(org.teiid.api.exception.query.QueryValidatorException) UpdateInfo(org.teiid.query.validator.UpdateValidator.UpdateInfo)

Aggregations

UpdateInfo (org.teiid.query.validator.UpdateValidator.UpdateInfo)7 TeiidException (org.teiid.core.TeiidException)2 RuleMergeCriteria (org.teiid.query.optimizer.relational.rules.RuleMergeCriteria)2 LanguageObject (org.teiid.query.sql.LanguageObject)2 Command (org.teiid.query.sql.lang.Command)2 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)2 ExpressionEvaluationException (org.teiid.api.exception.query.ExpressionEvaluationException)1 QueryParserException (org.teiid.api.exception.query.QueryParserException)1 QueryResolverException (org.teiid.api.exception.query.QueryResolverException)1 QueryValidatorException (org.teiid.api.exception.query.QueryValidatorException)1 FunctionDescriptor (org.teiid.query.function.FunctionDescriptor)1 FunctionLibrary (org.teiid.query.function.FunctionLibrary)1 QueryNode (org.teiid.query.mapping.relational.QueryNode)1 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)1 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)1 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)1 UpdateValidator (org.teiid.query.validator.UpdateValidator)1 UpdateMapping (org.teiid.query.validator.UpdateValidator.UpdateMapping)1 ValidationVisitor (org.teiid.query.validator.ValidationVisitor)1 SaxonXQueryExpression (org.teiid.query.xquery.saxon.SaxonXQueryExpression)1