use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.
the class RelationalPlanner method isPushdownValid.
private boolean isPushdownValid(WithQueryCommand with, SetQuery setQuery, Object modelID, QueryCommand withCommand, RelationalPlan subPlan1) throws QueryMetadataException, TeiidComponentException {
AccessNode aNode1 = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan1);
if (aNode1 == null) {
return false;
}
Object modelID1 = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode1, false);
QueryCommand withCommand1 = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode1);
if (modelID1 == null || withCommand1 == null) {
return false;
}
// if we are the same connector for each, then we should be good to proceed
if (CapabilitiesUtil.isSameConnector(modelID, modelID1, metadata, capFinder)) {
SetQuery pushdownSetQuery = new SetQuery(Operation.UNION, setQuery.isAll(), withCommand, withCommand1);
WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), pushdownSetQuery);
wqc.setRecursive(true);
this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc);
return true;
}
return false;
}
use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.
the class RelationalPlanner method assignWithClause.
private void assignWithClause(RelationalNode node, LinkedHashMap<String, WithQueryCommand> pushdownWith, boolean repeated) throws QueryPlannerException, TeiidComponentException {
List<SubqueryContainer<?>> subCommands = new ArrayList<SubqueryContainer<?>>();
if (node instanceof SubqueryAwareRelationalNode) {
for (LanguageObject lo : ((SubqueryAwareRelationalNode) node).getObjects()) {
ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(lo, subCommands);
if (!subCommands.isEmpty()) {
for (SubqueryContainer<?> subquery : subCommands) {
if (subquery.getCommand().getProcessorPlan() instanceof RelationalPlan) {
assignWithClause(((RelationalPlan) subquery.getCommand().getProcessorPlan()).getRootNode(), pushdownWith, repeated | (subquery.getCommand().getCorrelatedReferences() != null && !subquery.getCommand().getCorrelatedReferences().asMap().isEmpty()));
}
}
subCommands.clear();
}
}
}
if (node instanceof PlanExecutionNode) {
// need to check for nested relational plans. these are created by things such as the semi-join optimization in rulemergevirtual
ProcessorPlan plan = ((PlanExecutionNode) node).getProcessorPlan();
if (plan instanceof RelationalPlan) {
// other types of plans will be contained under non-relational plans, which would be out of scope for the parent with
node = ((RelationalPlan) plan).getRootNode();
}
}
if (node instanceof AccessNode) {
AccessNode accessNode = (AccessNode) node;
Map<GroupSymbol, RelationalPlan> subplans = accessNode.getSubPlans();
if (subplans != null) {
for (RelationalPlan subplan : subplans.values()) {
assignWithClause(subplan.getRootNode(), pushdownWith, false);
}
}
Command command = accessNode.getCommand();
if (command instanceof Insert && ((Insert) command).getQueryExpression() != null) {
command = ((Insert) command).getQueryExpression();
}
if (command instanceof QueryCommand) {
if (this.withGroups == null) {
this.withGroups = new TreeSet<GroupSymbol>(nonCorrelatedComparator);
} else {
this.withGroups.clear();
}
GroupCollectorVisitor.getGroupsIgnoreInlineViewsAndEvaluatableSubqueries(command, this.withGroups);
List<WithQueryCommand> with = new ArrayList<WithQueryCommand>();
discoverWith(pushdownWith, command, with, new ArrayList<GroupSymbol>(this.withGroups));
if (!with.isEmpty()) {
List<WithQueryCommand> pushed = new ArrayList<WithQueryCommand>(with);
final Map<GroupSymbol, Integer> order = new HashMap<GroupSymbol, Integer>();
for (WithQueryCommand withQueryCommand : pushdownWith.values()) {
order.put(withQueryCommand.getGroupSymbol(), order.size());
}
Collections.sort(with, new Comparator<WithQueryCommand>() {
@Override
public int compare(WithQueryCommand o1, WithQueryCommand o2) {
return order.get(o1.getGroupSymbol()).compareTo(order.get(o2.getGroupSymbol()));
}
});
// pull up the with from the subqueries
for (int i = 0; i < with.size(); i++) {
WithQueryCommand wqc = with.get(i);
List<WithQueryCommand> with2 = wqc.getCommand().getWith();
if (with2 != null) {
with.addAll(i, with2);
i += with2.size();
wqc.getCommand().setWith(null);
}
}
QueryCommand query = (QueryCommand) command;
List<SubqueryContainer<?>> subqueries = ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(query);
this.withGroups.clear();
for (WithQueryCommand wqc : with) {
withGroups.add(wqc.getGroupSymbol());
}
pullupWith(with, subqueries, withGroups);
if (query.getWith() != null) {
// we need to accumulate as a with clause could have been used at a lower scope
query.getWith().addAll(with);
} else {
query.setWith(with);
}
for (WithQueryCommand wqc : pushed) {
Object o = this.withPlanningState.pushdownState.get(wqc.getGroupSymbol().getName());
if (o == null) {
if (!repeated) {
if (accessNode.info != null) {
o = accessNode.info.id;
} else {
o = Boolean.FALSE;
}
} else {
o = Boolean.TRUE;
}
} else if (o instanceof Integer) {
// check for shared
if (accessNode.info == null || !o.equals(accessNode.info.id)) {
o = Boolean.TRUE;
}
} else {
o = Boolean.TRUE;
}
this.withPlanningState.pushdownState.put(wqc.getGroupSymbol().getName(), o);
}
// TODO: this should be based upon whether any of the need evaluated
accessNode.setShouldEvaluateExpressions(true);
}
}
}
// Recurse through children
RelationalNode[] children = node.getChildren();
for (int i = 0; i < node.getChildCount(); i++) {
assignWithClause(children[i], pushdownWith, repeated);
}
}
use of org.teiid.query.processor.relational.AccessNode 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);
}
use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.
the class CriteriaCapabilityValidatorVisitor method getAccessNode.
public static AccessNode getAccessNode(ProcessorPlan plan) {
if (!(plan instanceof RelationalPlan)) {
return null;
}
RelationalPlan rplan = (RelationalPlan) plan;
// Check that the plan is just an access node
RelationalNode accessNode = rplan.getRootNode();
if (accessNode instanceof LimitNode) {
LimitNode ln = (LimitNode) accessNode;
if (!ln.isImplicit()) {
return null;
}
accessNode = ln.getChildren()[0];
}
if (!(accessNode instanceof AccessNode)) {
return null;
}
return (AccessNode) accessNode;
}
use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.
the class CriteriaCapabilityValidatorVisitor method validateSubqueryPushdown.
/**
* Return null if the subquery cannot be pushed down, otherwise the model
* id of the pushdown target.
* @param subqueryContainer
* @param critNodeModelID
* @param metadata
* @param capFinder
* @return
* @throws TeiidComponentException
*/
public static Object validateSubqueryPushdown(SubqueryContainer<?> subqueryContainer, Object critNodeModelID, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord) throws TeiidComponentException {
ProcessorPlan plan = subqueryContainer.getCommand().getProcessorPlan();
if (plan != null) {
AccessNode aNode = getAccessNode(plan);
if (aNode == null) {
return null;
}
critNodeModelID = validateCommandPushdown(critNodeModelID, metadata, capFinder, aNode, true);
}
if (critNodeModelID == null) {
return null;
}
// Check whether source supports correlated subqueries and if not, whether criteria has them
SymbolMap refs = subqueryContainer.getCommand().getCorrelatedReferences();
try {
if (refs != null && !refs.asMap().isEmpty()) {
if (!CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_CORRELATED, critNodeModelID, metadata, capFinder)) {
return null;
}
if (!CapabilitiesUtil.supports(Capability.SUBQUERY_CORRELATED_LIMIT, critNodeModelID, metadata, capFinder)) {
QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
if (command.getLimit() != null && !command.getLimit().isImplicit()) {
return null;
}
}
// but this is only an issue with deeply nested subqueries
if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(subqueryContainer.getCommand(), critNodeModelID, metadata, capFinder, analysisRecord)) {
return null;
}
} else if (CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_ONLY_CORRELATED, critNodeModelID, metadata, capFinder)) {
return null;
}
} catch (QueryMetadataException e) {
throw new TeiidComponentException(QueryPlugin.Event.TEIID30271, e);
}
if (!CapabilitiesUtil.supports(Capability.SUBQUERY_COMMON_TABLE_EXPRESSIONS, critNodeModelID, metadata, capFinder) && subqueryContainer.getCommand() instanceof QueryCommand) {
QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
if (command.getWith() != null) {
return null;
}
}
// Found no reason why this node is not eligible
return critNodeModelID;
}
Aggregations