use of org.teiid.query.processor.relational.RelationalNode in project teiid by teiid.
the class RelationalPlanner method planWith.
private void planWith(PlanNode plan, Command command) throws QueryPlannerException, QueryMetadataException, TeiidComponentException, QueryResolverException {
if (this.withPlanningState.withList.isEmpty()) {
return;
}
// TODO: merge this logic inline with the main rule execution.
RuleStack stack = new RuleStack();
stack.push(new RuleAssignOutputElements(false));
if (hints.hasRowBasedSecurity) {
stack.push(new RuleApplySecurity());
}
// use a temporary planner to run just the assign output elements
RelationalPlanner planner = new RelationalPlanner();
// we don't want to trigger the with processing for just projection
planner.processWith = false;
planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
planner.executeRules(stack, plan);
// discover all of the usage
List<Command> commands = CommandCollectorVisitor.getCommands(command, true);
while (!commands.isEmpty()) {
Command cmd = commands.remove(commands.size() - 1);
commands.addAll(CommandCollectorVisitor.getCommands(cmd, true));
try {
PlanNode temp = planner.generatePlan((Command) cmd.clone());
stack.push(new RuleAssignOutputElements(false));
planner.executeRules(stack, temp);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
}
// plan and minimize projection
for (WithQueryCommand with : this.withPlanningState.withList.values()) {
QueryCommand subCommand = with.getCommand();
TempMetadataID tid = (TempMetadataID) with.getGroupSymbol().getMetadataID();
if (tid.getTableData().getModel() != TempMetadataAdapter.TEMP_MODEL) {
tid.getTableData().setModel(null);
}
List<TempMetadataID> elements = tid.getElements();
List<Integer> toRemove = new ArrayList<Integer>();
for (int i = elements.size() - 1; i >= 0; i--) {
TempMetadataID elem = elements.get(i);
if (!elem.isAccessed()) {
toRemove.add(i);
}
}
// the definition of the with clause consistent
if (!toRemove.isEmpty()) {
if (with.isRecursive()) {
SetQuery setQuery = (SetQuery) subCommand;
setQuery.setLeftQuery(removeUnusedProjection(with, setQuery.getLeftQuery(), elements, toRemove));
setQuery.setRightQuery(removeUnusedProjection(with, setQuery.getRightQuery(), elements, toRemove));
} else {
subCommand = removeUnusedProjection(with, subCommand, elements, toRemove);
with.setCommand(subCommand);
}
}
if (with.isRecursive()) {
SetQuery setQuery = (SetQuery) subCommand;
QueryCommand qc = setQuery.getLeftQuery();
final RelationalPlan subPlan = optimize(qc);
qc.setProcessorPlan(subPlan);
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan);
Object modelID = null;
QueryCommand withCommand = null;
if (aNode != null) {
modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
if (modelID != null) {
if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.RECURSIVE_COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
modelID = null;
} else {
withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (withCommand != null) {
// provisionally set the source
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
}
}
}
}
// now that we possibly have a model id, plan the recursive part
QueryCommand qc1 = setQuery.getRightQuery();
RelationalPlan subPlan1 = optimize((Command) qc1.clone());
qc1.setProcessorPlan(subPlan1);
if (!isPushdownValid(with, setQuery, modelID, withCommand, subPlan1) && withCommand != null) {
// reset the source to null and replan
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(null);
subPlan1 = optimize(qc1);
qc1.setProcessorPlan(subPlan1);
}
continue;
}
RelationalPlan subPlan = optimize(subCommand);
subCommand.setProcessorPlan(subPlan);
RelationalPlan procPlan = subPlan;
RelationalNode root = procPlan.getRootNode();
Number planCardinality = root.getEstimateNodeCardinality();
if (planCardinality != null) {
((TempMetadataID) with.getGroupSymbol().getMetadataID()).setCardinality(planCardinality.intValue());
}
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(procPlan);
if (aNode == null) {
continue;
}
Object modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
QueryCommand withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (modelID == null || withCommand == null) {
continue;
}
if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
continue;
}
WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), withCommand);
wqc.setNoInline(with.isNoInline());
((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc);
}
}
use of org.teiid.query.processor.relational.RelationalNode 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.RelationalNode 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.RelationalNode in project teiid by teiid.
the class TestDependentJoins method getDependentGroups.
static void getDependentGroups(RelationalNode node, Set<String> depGroups, boolean depdenent) {
if (node instanceof AccessNode) {
if (node instanceof DependentAccessNode) {
if (!depdenent) {
return;
}
} else if (depdenent) {
return;
}
AccessNode accessNode = (AccessNode) node;
Command depCommand = accessNode.getCommand();
Collection<GroupSymbol> groupSymbols = GroupCollectorVisitor.getGroups(depCommand, true);
for (GroupSymbol groupSymbol : groupSymbols) {
depGroups.add(groupSymbol.getNonCorrelationName().toUpperCase());
}
}
// Recurse through children
RelationalNode[] children = node.getChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] != null) {
getDependentGroups(node.getChildren()[i], depGroups, depdenent);
}
}
}
use of org.teiid.query.processor.relational.RelationalNode in project teiid by teiid.
the class TestJoinOptimization method testOuterJoinRemoval.
@Test
public void testOuterJoinRemoval() throws Exception {
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false);
caps.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false);
ProcessorPlan plan = // $NON-NLS-1$
TestOptimizer.helpPlan(// $NON-NLS-1$
"SELECT * from pm1.g1 inner join (pm1.g2 left outer join pm1.g3 on pm1.g2.e1=pm1.g3.e1) on pm1.g1.e1=pm1.g3.e1", RealMetadataFactory.example1Cached(), new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g2 AS g_0 ORDER BY c_0", "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g1 AS g_0 ORDER BY c_0", "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g3 AS g_0 ORDER BY c_0" }, new DefaultCapabilitiesFinder(caps), // $NON-NLS-1$
ComparisonMode.EXACT_COMMAND_STRING);
RelationalNode node = ((RelationalPlan) plan).getRootNode().getChildren()[0];
assertTrue(node instanceof JoinNode);
node = node.getChildren()[0];
assertTrue(node instanceof JoinNode);
assertEquals(JoinType.JOIN_INNER, ((JoinNode) node).getJoinType());
}
Aggregations