@Test public void shouldReplaceViewWithPlanForViewWithSingleTable() { PlanNode project = new PlanNode(Type.PROJECT, selector("v1")); PlanNode select1 = new PlanNode(Type.SELECT, project, selector("v1")); PlanNode select2 = new PlanNode(Type.SELECT, select1, selector("v1")); PlanNode select3 = new PlanNode(Type.SELECT, select2, selector("v1")); PlanNode source = new PlanNode(Type.SOURCE, select3, selector("v1")); source.setProperty(Property.SOURCE_NAME, selector("v1")); PlanNode viewProject = new PlanNode(Type.PROJECT, selector("t1")); PlanNode viewSelect = new PlanNode(Type.SELECT, viewProject, selector("t1")); PlanNode viewSource = new PlanNode(Type.SOURCE, viewSelect, selector("t1")); viewProject.setProperty(Property.PROJECT_COLUMNS, columns(column("t1", "c11"), column("t1", "c12"))); viewSelect.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("t1"), "c13"), Operator.LESS_THAN, new Literal(3L))); viewSource.setProperty(Property.SOURCE_NAME, selector("t1")); viewSource.setProperty(Property.SOURCE_COLUMNS, schemata.getTable(selector("t1")).getColumns()); PlanNode result = rule.execute(context, project, new LinkedList<OptimizerRule>()); assertThat(result.isSameAs(project), is(true)); assertChildren(project, select1); assertChildren(select1, select2); assertChildren(select2, select3); }
@Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { CanonicalPlanner planner = new CanonicalPlanner(); Schemata schemata = context.getSchemata(); Set<PlanNode> processedSources = new HashSet<PlanNode>(); boolean foundViews = false; do { foundViews = false; for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) { if (processedSources.contains(sourceNode)) continue; processedSources.add(sourceNode); SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class); SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class); Table table = schemata.getTable(tableName); if (table instanceof View) { View view = (View)table; PlanNode viewPlan = planner.createPlan(context, view.getDefinition()); if (viewPlan == null) continue; PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT); if (viewProjectNode.getSelectors().size() == 1) { SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName; SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next(); Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName); PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements); if (!context.getHints().validateColumnExistance) { PlanNode project = sourceNode.findAncestor(Type.PROJECT); if (project != null) { List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class); viewPlan = PlanUtil.addMissingProjectColumns(context, viewProjectNode, projectedColumns); assert viewPlan != null; } } } sourceNode.addLastChild(viewPlan); sourceNode.extractFromParent(); PlanNode parent = viewPlan.getParent(); if (parent != null) { PlanUtil.ColumnMapping aliasMappings = null; if (tableAlias != null) { aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan); PlanUtil.replaceViewReferences(context, parent, aliasMappings); } PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan); PlanUtil.replaceViewReferences(context, parent, viewMappings); } if (viewPlan.is(Type.PROJECT)) { PlanNode node = viewPlan.getParent(); while (node != null) { if (node.isOneOf(Type.JOIN)) break; if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) { viewPlan.extractFromParent(); break; } node = node.getParent(); } } foundViews = true; } } } while (foundViews); if (foundViews) { if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) { ruleStack.addFirst(RaiseSelectCriteria.INSTANCE); ruleStack.addFirst(PushSelectCriteria.INSTANCE); } ruleStack.addFirst(this); } return plan; }
ReplaceViews implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { CanonicalPlanner planner = new CanonicalPlanner(); Schemata schemata = context.getSchemata(); Set<PlanNode> processedSources = new HashSet<PlanNode>(); boolean foundViews = false; do { foundViews = false; for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) { if (processedSources.contains(sourceNode)) continue; processedSources.add(sourceNode); SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class); SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class); Table table = schemata.getTable(tableName); if (table instanceof View) { View view = (View)table; PlanNode viewPlan = planner.createPlan(context, view.getDefinition()); if (viewPlan == null) continue; PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT); if (viewProjectNode.getSelectors().size() == 1) { SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName; SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next(); Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName); PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements); if (!context.getHints().validateColumnExistance) { PlanNode project = sourceNode.findAncestor(Type.PROJECT); if (project != null) { List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class); viewPlan = PlanUtil.addMissingProjectColumns(context, viewProjectNode, projectedColumns); assert viewPlan != null; } } } sourceNode.addLastChild(viewPlan); sourceNode.extractFromParent(); PlanNode parent = viewPlan.getParent(); if (parent != null) { PlanUtil.ColumnMapping aliasMappings = null; if (tableAlias != null) { aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan); PlanUtil.replaceViewReferences(context, parent, aliasMappings); } PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan); PlanUtil.replaceViewReferences(context, parent, viewMappings); } if (viewPlan.is(Type.PROJECT)) { PlanNode node = viewPlan.getParent(); while (node != null) { if (node.isOneOf(Type.JOIN)) break; if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) { viewPlan.extractFromParent(); break; } node = node.getParent(); } } foundViews = true; } } } while (foundViews); if (foundViews) { if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) { ruleStack.addFirst(RaiseSelectCriteria.INSTANCE); ruleStack.addFirst(PushSelectCriteria.INSTANCE); } ruleStack.addFirst(this); } return plan; } }
ReplaceViews implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { CanonicalPlanner planner = new CanonicalPlanner(); Schemata schemata = context.getSchemata(); Set<PlanNode> processedSources = new HashSet<PlanNode>(); boolean foundViews = false; do { foundViews = false; for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) { if (processedSources.contains(sourceNode)) continue; processedSources.add(sourceNode); SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class); SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class); Table table = schemata.getTable(tableName); if (table instanceof View) { View view = (View)table; PlanNode viewPlan = planner.createPlan(context, view.getDefinition()); if (viewPlan == null) continue; PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT); if (viewProjectNode.getSelectors().size() == 1) { SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName; SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next(); Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName); PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements); if (!context.getHints().validateColumnExistance) { PlanNode project = sourceNode.findAncestor(Type.PROJECT); if (project != null) { List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class); viewPlan = PlanUtil.addMissingProjectColumns(context, viewProjectNode, projectedColumns); assert viewPlan != null; } } } sourceNode.addLastChild(viewPlan); sourceNode.extractFromParent(); PlanNode parent = viewPlan.getParent(); if (parent != null) { PlanUtil.ColumnMapping aliasMappings = null; if (tableAlias != null) { aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan); PlanUtil.replaceViewReferences(context, parent, aliasMappings); } PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan); PlanUtil.replaceViewReferences(context, parent, viewMappings); } if (viewPlan.is(Type.PROJECT)) { PlanNode node = viewPlan.getParent(); while (node != null) { if (node.isOneOf(Type.JOIN)) break; if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) { viewPlan.extractFromParent(); break; } node = node.getParent(); } } foundViews = true; } } } while (foundViews); if (foundViews) { if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) { ruleStack.addFirst(RaiseSelectCriteria.INSTANCE); ruleStack.addFirst(PushSelectCriteria.INSTANCE); } ruleStack.addFirst(this); } return plan; }  }
ReplaceViews implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { CanonicalPlanner planner = new CanonicalPlanner(); Schemata schemata = context.getSchemata(); Set<PlanNode> processedSources = new HashSet<PlanNode>(); boolean foundViews = false; do { foundViews = false; for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) { if (processedSources.contains(sourceNode)) continue; processedSources.add(sourceNode); SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class); SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class); Table table = schemata.getTable(tableName); if (table instanceof View) { View view = (View)table; PlanNode viewPlan = planner.createPlan(context, view.getDefinition()); if (viewPlan == null) continue; PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT); if (viewProjectNode.getSelectors().size() == 1) { SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName; SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next(); Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName); PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements); if (!context.getHints().validateColumnExistance) { PlanNode project = sourceNode.findAncestor(Type.PROJECT); if (project != null) { List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class); viewPlan = PlanUtil.addMissingProjectColumns(context, viewProjectNode, projectedColumns); assert viewPlan != null; } } } sourceNode.addLastChild(viewPlan); sourceNode.extractFromParent(); PlanNode parent = viewPlan.getParent(); if (parent != null) { PlanUtil.ColumnMapping aliasMappings = null; if (tableAlias != null) { aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan); PlanUtil.replaceViewReferences(context, parent, aliasMappings); } PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan); PlanUtil.replaceViewReferences(context, parent, viewMappings); } if (viewPlan.is(Type.PROJECT)) { PlanNode node = viewPlan.getParent(); while (node != null) { if (node.isOneOf(Type.JOIN)) break; if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) { viewPlan.extractFromParent(); break; } node = node.getParent(); } } foundViews = true; } } } while (foundViews); if (foundViews) { if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) { ruleStack.addFirst(RaiseSelectCriteria.INSTANCE); ruleStack.addFirst(PushSelectCriteria.INSTANCE); } ruleStack.addFirst(this); } return plan; }  @Override PlanNode execute( QueryContext context,
                             PlanNode plan,
                             LinkedList<OptimizerRule> ruleStack ); @Override String toString(); }
ReplaceViews implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { CanonicalPlanner planner = new CanonicalPlanner(); Schemata schemata = context.getSchemata(); Set<PlanNode> processedSources = new HashSet<PlanNode>(); boolean foundViews = false; do { foundViews = false; for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) { if (processedSources.contains(sourceNode)) continue; processedSources.add(sourceNode); SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class); SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class); Table table = schemata.getTable(tableName); if (table instanceof View) { View view = (View)table; PlanNode viewPlan = planner.createPlan(context, view.getDefinition()); if (viewPlan == null) continue; PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT); if (viewProjectNode.getSelectors().size() == 1) { SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName; SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next(); Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName); PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements); if (!context.getHints().validateColumnExistance) { PlanNode project = sourceNode.findAncestor(Type.PROJECT); if (project != null) { List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class); viewPlan = PlanUtil.addMissingProjectColumns(context, viewProjectNode, projectedColumns); assert viewPlan != null; } } } sourceNode.addLastChild(viewPlan); sourceNode.extractFromParent(); PlanNode parent = viewPlan.getParent(); if (parent != null) { PlanUtil.ColumnMapping aliasMappings = null; if (tableAlias != null) { aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan); PlanUtil.replaceViewReferences(context, parent, aliasMappings); } PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan); PlanUtil.replaceViewReferences(context, parent, viewMappings); } if (viewPlan.is(Type.PROJECT)) { PlanNode node = viewPlan.getParent(); while (node != null) { if (node.isOneOf(Type.JOIN)) break; if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) { viewPlan.extractFromParent(); break; } node = node.getParent(); } } foundViews = true; } } } while (foundViews); if (foundViews) { if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) { ruleStack.addFirst(RaiseSelectCriteria.INSTANCE); ruleStack.addFirst(PushSelectCriteria.INSTANCE); } ruleStack.addFirst(this); } return plan; }  @Override PlanNode execute( QueryContext context,
                             PlanNode plan,
                             LinkedList<OptimizerRule> ruleStack ); @Override String toString(); static final ReplaceViews INSTANCE; }