Search in sources :

Example 6 with ExpressionMappingVisitor

use of org.teiid.query.sql.visitor.ExpressionMappingVisitor in project teiid by teiid.

the class RuleCollapseSource method prepareSubquery.

public static void prepareSubquery(SubqueryContainer container) {
    RelationalPlan subqueryPlan = (RelationalPlan) container.getCommand().getProcessorPlan();
    AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(subqueryPlan);
    QueryCommand command = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
    if (command == null) {
        return;
    }
    final SymbolMap map = container.getCommand().getCorrelatedReferences();
    if (map != null) {
        ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(map);
        DeepPostOrderNavigator.doVisit(command, visitor);
    }
    command.setProcessorPlan(container.getCommand().getProcessorPlan());
    boolean removeLimit = false;
    if (container instanceof ExistsCriteria) {
        removeLimit = !((ExistsCriteria) container).shouldEvaluate();
    } else if (container instanceof ScalarSubquery) {
        removeLimit = !((ScalarSubquery) container).shouldEvaluate();
    }
    if (removeLimit && command.getLimit() != null && command.getLimit().isImplicit()) {
        command.setLimit(null);
    }
    container.setCommand(command);
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap) AccessNode(org.teiid.query.processor.relational.AccessNode) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor)

Example 7 with ExpressionMappingVisitor

use of org.teiid.query.sql.visitor.ExpressionMappingVisitor in project teiid by teiid.

the class TriggerActionPlanner method rewritePlan.

/**
 * look for the simple case of a mapping to a single insert statement trigger action - and reconstruct the plan as a single insert
 * TODO: need internal primitives for delete/update batching in a loop for delete/update cases
 */
private ProcessorPlan rewritePlan(TriggerAction ta, IDGenerator idGenerator, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context, QueryCommand query, Map<ElementSymbol, Expression> mapping, Insert insert) throws QueryMetadataException, QueryResolverException, TeiidComponentException, QueryPlannerException {
    if (ta.getBlock().getStatements().size() != 1) {
        return null;
    }
    Statement s = ta.getBlock().getStatements().get(0);
    if (!(s instanceof CommandStatement)) {
        return null;
    }
    CommandStatement cs = (CommandStatement) s;
    if (!(cs.getCommand() instanceof Insert)) {
        return null;
    }
    Insert mapped = (Insert) cs.getCommand();
    if (mapped.getQueryExpression() != null) {
        return null;
    }
    if (insert.getQueryExpression() != null) {
        // use a unique inline view name to make the final remapping easier
        GroupSymbol group = new GroupSymbol("X");
        Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroups(query, true);
        for (int i = 0; groups.contains(group); i++) {
            group.setName("X_" + i);
        }
        List<Expression> projectedSymbols = query.getProjectedSymbols();
        Query queryExpression = QueryRewriter.createInlineViewQuery(group, query, metadata, projectedSymbols);
        List<Expression> viewSymbols = new ArrayList<Expression>(queryExpression.getSelect().getSymbols());
        // switch to the values
        queryExpression.getSelect().clearSymbols();
        List<Expression> values = mapped.getValues();
        queryExpression.getSelect().addSymbols(values);
        values.clear();
        // update the mapping to the view symbols
        for (int i = 0; i < projectedSymbols.size(); i++) {
            ElementSymbol es = insert.getVariables().get(i);
            mapping.put(new ElementSymbol(es.getShortName(), new GroupSymbol(SQLConstants.Reserved.NEW)), SymbolMap.getExpression(viewSymbols.get(i)));
        }
        // map to the query form - changes references back to element form
        SymbolMap queryMapping = new SymbolMap();
        queryMapping.asUpdatableMap().putAll(mapping);
        ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(queryMapping);
        DeepPostOrderNavigator.doVisit(queryExpression.getSelect(), visitor);
        // now we can return a plan based off a single insert statement
        mapped.setQueryExpression(queryExpression);
        return QueryOptimizer.optimizePlan(mapped, metadata, idGenerator, capFinder, analysisRecord, context);
    }
    List<Expression> values = mapped.getValues();
    SymbolMap queryMapping = new SymbolMap();
    queryMapping.asUpdatableMap().putAll(mapping);
    ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(queryMapping);
    Select select = new Select();
    select.addSymbols(values);
    DeepPostOrderNavigator.doVisit(select, visitor);
    values.clear();
    for (Expression ex : select.getSymbols()) {
        try {
            values.add(QueryRewriter.rewriteExpression(SymbolMap.getExpression(ex), context, metadata));
        } catch (TeiidProcessingException e) {
            throw new QueryPlannerException(e);
        }
    }
    return QueryOptimizer.optimizePlan(mapped, metadata, idGenerator, capFinder, analysisRecord, context);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) CommandStatement(org.teiid.query.sql.proc.CommandStatement) Statement(org.teiid.query.sql.proc.Statement) ArrayList(java.util.ArrayList) SymbolMap(org.teiid.query.sql.util.SymbolMap) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor) TeiidProcessingException(org.teiid.core.TeiidProcessingException) CommandStatement(org.teiid.query.sql.proc.CommandStatement) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 8 with ExpressionMappingVisitor

use of org.teiid.query.sql.visitor.ExpressionMappingVisitor in project teiid by teiid.

the class QueryRewriter method rewriteForWriteThrough.

private Command rewriteForWriteThrough(ProcedureContainer update) throws TeiidComponentException, QueryMetadataException, QueryResolverException, TeiidProcessingException {
    if (processing || update.hasTag(WRITE_THROUGH) || !metadata.hasMaterialization(update.getGroup().getMetadataID()) || !Boolean.valueOf(metadata.getExtensionProperty(update.getGroup().getMetadataID(), MaterializationMetadataRepository.MATVIEW_WRITE_THROUGH, false))) {
        return null;
    }
    // internal
    // update view ... where predicate - mark as write through
    // loop on (select pk from view where predicate) - mark as write through, it's ok that this will use cache
    // refreshMatView ...
    // end
    // external
    // update view ... where predicate - mark as write through
    // update target ... where predicate - mark as write through
    Block block = new Block();
    block.setAtomic(true);
    ProcedureContainer clone = (ProcedureContainer) update.clone();
    // $NON-NLS-1$
    GroupSymbol temp = new GroupSymbol("#temp");
    if (context.getGroups().contains(temp.getName())) {
        temp = RulePlaceAccess.recontextSymbol(temp, context.getGroups());
        temp.setDefinition(null);
    }
    Query q = new Query();
    q.setSelect(new Select(Arrays.asList(new MultipleElementSymbol())));
    q.setFrom(new From(Arrays.asList(new UnaryFromClause(temp))));
    update.addTag(WRITE_THROUGH);
    block.addStatement(new CommandStatement(update));
    ElementSymbol rowCount = new ElementSymbol(ProcedureReservedWords.ROWCOUNT);
    // $NON-NLS-1$
    ElementSymbol val = new ElementSymbol("val");
    DeclareStatement ds = new DeclareStatement(val, DataTypeManager.DefaultDataTypes.INTEGER, rowCount);
    block.addStatement(ds);
    final Object gid = update.getGroup().getMetadataID();
    Object target = metadata.getMaterialization(gid);
    if (target != null) {
        final GroupSymbol newGroup = new GroupSymbol(metadata.getFullName(target));
        newGroup.setMetadataID(target);
        ExpressionMappingVisitor emv = new ExpressionMappingVisitor(null) {

            public Expression replaceExpression(Expression element) {
                if (element instanceof ElementSymbol) {
                    ElementSymbol es = (ElementSymbol) element;
                    if (es.getGroupSymbol().getMetadataID() == gid) {
                        es.setGroupSymbol(newGroup);
                    }
                }
                return element;
            }
        };
        if (clone instanceof Update) {
            Update u = (Update) clone;
            for (SetClause sc : u.getChangeList().getClauses()) {
                sc.setSymbol(new ElementSymbol(sc.getSymbol().getShortName(), newGroup.clone()));
                PreOrPostOrderNavigator.doVisit(sc, emv, PreOrPostOrderNavigator.POST_ORDER);
            }
            u.setGroup(newGroup);
        } else {
            ((Delete) clone).setGroup(newGroup);
        }
        PreOrPostOrderNavigator.doVisit(((FilteredCommand) clone).getCriteria(), emv, PreOrPostOrderNavigator.POST_ORDER);
        clone.setUpdateInfo(null);
        clone.addTag(WRITE_THROUGH);
        block.addStatement(new CommandStatement(clone));
    } else {
        Object key = metadata.getPrimaryKey(update.getGroup().getMetadataID());
        if (key == null) {
            // we need a key for this logic to work
            return null;
        }
        Block b = new Block();
        List<Object> ids = metadata.getElementIDsInKey(key);
        Select select = new Select();
        for (Object id : ids) {
            select.addSymbol(new ElementSymbol(metadata.getName(id)));
        }
        if (clone instanceof Update) {
            Update u = (Update) clone;
            for (SetClause sc : u.getChangeList().getClauses()) {
                if (ids.contains(sc.getSymbol().getMetadataID())) {
                    // corner case of an update manipulating the primary key
                    return null;
                }
            }
        }
        Query keys = new Query();
        keys.setSelect(select);
        keys.setFrom(new From(Arrays.asList(new UnaryFromClause(update.getGroup()))));
        if (((FilteredCommand) clone).getCriteria() != null) {
            keys.setCriteria((Criteria) ((FilteredCommand) clone).getCriteria().clone());
        }
        // $NON-NLS-1$
        LoopStatement loop = new LoopStatement(b, keys, "x");
        StoredProcedure sp = new StoredProcedure();
        // $NON-NLS-1$
        sp.setProcedureName("SYSAdmin.refreshMatViewRow");
        sp.setParameter(new SPParameter(1, new Constant(metadata.getFullName(update.getGroup().getMetadataID()))));
        int index = 2;
        for (Object id : ids) {
            sp.setParameter(new SPParameter(index++, new ElementSymbol(metadata.getName(id))));
        }
        b.addStatement(new CommandStatement(sp));
        block.addStatement(loop);
    }
    Query result = new Query();
    result.setSelect(new Select(Arrays.asList(val)));
    block.addStatement(new CommandStatement(result));
    CreateProcedureCommand command = new CreateProcedureCommand(block);
    QueryResolver.resolveCommand(command, metadata);
    return rewriteCommand(command, false);
}
Also used : ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 9 with ExpressionMappingVisitor

use of org.teiid.query.sql.visitor.ExpressionMappingVisitor in project teiid by teiid.

the class QueryRewriter method rewriteInherentDelete.

private Command rewriteInherentDelete(Delete delete, UpdateInfo info) throws QueryMetadataException, TeiidComponentException, QueryResolverException, TeiidProcessingException {
    UpdateMapping mapping = info.getDeleteTarget();
    if (info.isSimple()) {
        Collection<ElementSymbol> elements = getAllElementsUsed(delete, delete.getGroup());
        UpdateMapping fullMapping = info.findUpdateMapping(elements, false);
        if (fullMapping != null) {
            delete.setGroup(mapping.getGroup().clone());
            // TODO: properly handle correlated references
            DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
            delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata, Command.TYPE_DELETE, true));
            if (info.getViewDefinition().getCriteria() != null) {
                delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria) info.getViewDefinition().getCriteria().clone()));
            }
            return rewriteDelete(delete);
        }
    }
    Query query = (Query) info.getViewDefinition().clone();
    query.setOrderBy(null);
    SymbolMap expressionMapping = SymbolMap.createSymbolMap(delete.getGroup(), query.getProjectedSymbols(), metadata);
    query.setSelect(new Select());
    ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
    Criteria crit = delete.getCriteria();
    if (crit != null) {
        PostOrderNavigator.doVisit(crit, emv);
        query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
    }
    GroupSymbol group = mapping.getGroup();
    String correlationName = mapping.getCorrelatedName().getName();
    return createDeleteProcedure(delete, query, group, correlationName);
}
Also used : UpdateMapping(org.teiid.query.validator.UpdateValidator.UpdateMapping) SymbolMap(org.teiid.query.sql.util.SymbolMap) RuleMergeCriteria(org.teiid.query.optimizer.relational.rules.RuleMergeCriteria) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor)

Example 10 with ExpressionMappingVisitor

use of org.teiid.query.sql.visitor.ExpressionMappingVisitor in project teiid by teiid.

the class QueryRewriter method rewriteInherentUpdate.

private Command rewriteInherentUpdate(Update update, UpdateInfo info) throws QueryValidatorException, QueryMetadataException, TeiidComponentException, QueryResolverException, TeiidProcessingException {
    UpdateMapping mapping = info.findUpdateMapping(update.getChangeList().getClauseMap().keySet(), false);
    if (mapping == null) {
        throw new QueryValidatorException(QueryPlugin.Event.TEIID30376, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30376, update.getChangeList().getClauseMap().keySet()));
    }
    Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
    if (info.isSimple()) {
        Collection<ElementSymbol> elements = getAllElementsUsed(update, update.getGroup());
        UpdateMapping fullMapping = info.findUpdateMapping(elements, false);
        if (fullMapping != null) {
            update.setGroup(mapping.getGroup().clone());
            for (SetClause clause : update.getChangeList().getClauses()) {
                clause.setSymbol(symbolMap.get(clause.getSymbol()));
            }
            // TODO: properly handle correlated references
            DeepPostOrderNavigator.doVisit(update, new ExpressionMappingVisitor(symbolMap, true));
            if (info.getViewDefinition().getCriteria() != null) {
                update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria) info.getViewDefinition().getCriteria().clone()));
            }
            // resolve
            update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata, Command.TYPE_UPDATE, true));
            return rewriteUpdate(update);
        }
    }
    Query query = (Query) info.getViewDefinition().clone();
    query.setOrderBy(null);
    SymbolMap expressionMapping = SymbolMap.createSymbolMap(update.getGroup(), query.getProjectedSymbols(), metadata);
    SetClauseList setClauseList = (SetClauseList) update.getChangeList().clone();
    GroupSymbol varGroup = getVarGroup(update);
    ArrayList<Expression> selectSymbols = mapChangeList(setClauseList, symbolMap, varGroup);
    query.setSelect(new Select(selectSymbols));
    ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
    PostOrderNavigator.doVisit(query.getSelect(), emv);
    Criteria crit = update.getCriteria();
    if (crit != null) {
        PostOrderNavigator.doVisit(crit, emv);
        query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
    }
    GroupSymbol group = mapping.getGroup();
    String correlationName = mapping.getCorrelatedName().getName();
    return createUpdateProcedure(update, query, group, correlationName, setClauseList, varGroup, null);
}
Also used : UpdateMapping(org.teiid.query.validator.UpdateValidator.UpdateMapping) SymbolMap(org.teiid.query.sql.util.SymbolMap) RuleMergeCriteria(org.teiid.query.optimizer.relational.rules.RuleMergeCriteria) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor) QueryValidatorException(org.teiid.api.exception.query.QueryValidatorException)

Aggregations

ExpressionMappingVisitor (org.teiid.query.sql.visitor.ExpressionMappingVisitor)13 Expression (org.teiid.query.sql.symbol.Expression)6 SymbolMap (org.teiid.query.sql.util.SymbolMap)6 ArrayList (java.util.ArrayList)4 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 DataPolicy (org.teiid.adminapi.DataPolicy)2 TeiidRuntimeException (org.teiid.core.TeiidRuntimeException)2 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)2 RuleMergeCriteria (org.teiid.query.optimizer.relational.rules.RuleMergeCriteria)2 LanguageObject (org.teiid.query.sql.LanguageObject)2 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)2 Reference (org.teiid.query.sql.symbol.Reference)2 UpdateMapping (org.teiid.query.validator.UpdateValidator.UpdateMapping)2 List (java.util.List)1 DataPolicyMetadata (org.teiid.adminapi.impl.DataPolicyMetadata)1 PermissionMetaData (org.teiid.adminapi.impl.DataPolicyMetadata.PermissionMetaData)1 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)1 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)1