1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.graph.query.optimize;
25
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.LinkedList;
29 import java.util.Map;
30 import java.util.Set;
31 import net.jcip.annotations.Immutable;
32 import org.modeshape.graph.query.QueryContext;
33 import org.modeshape.graph.query.model.SelectorName;
34 import org.modeshape.graph.query.plan.CanonicalPlanner;
35 import org.modeshape.graph.query.plan.PlanNode;
36 import org.modeshape.graph.query.plan.PlanUtil;
37 import org.modeshape.graph.query.plan.PlanNode.Property;
38 import org.modeshape.graph.query.plan.PlanNode.Type;
39 import org.modeshape.graph.query.validate.Schemata;
40 import org.modeshape.graph.query.validate.Schemata.Table;
41 import org.modeshape.graph.query.validate.Schemata.View;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 @Immutable
74 public class ReplaceViews implements OptimizerRule {
75
76 public static final ReplaceViews INSTANCE = new ReplaceViews();
77
78
79
80
81
82
83
84 public PlanNode execute( QueryContext context,
85 PlanNode plan,
86 LinkedList<OptimizerRule> ruleStack ) {
87 CanonicalPlanner planner = new CanonicalPlanner();
88
89
90
91
92 Schemata schemata = context.getSchemata();
93 Set<PlanNode> processedSources = new HashSet<PlanNode>();
94 boolean foundViews = false;
95 do {
96 foundViews = false;
97 for (PlanNode sourceNode : plan.findAllAtOrBelow(Type.SOURCE)) {
98 if (processedSources.contains(sourceNode)) continue;
99 processedSources.add(sourceNode);
100
101
102 SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class);
103 SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class);
104 Table table = schemata.getTable(tableName);
105 if (table instanceof View) {
106 View view = (View)table;
107 PlanNode viewPlan = planner.createPlan(context, view.getDefinition());
108 if (viewPlan == null) continue;
109
110
111 PlanNode viewProjectNode = viewPlan.findAtOrBelow(Type.PROJECT);
112 if (viewProjectNode.getSelectors().size() == 1) {
113 SelectorName tableAliasOrName = tableAlias != null ? tableAlias : tableName;
114 SelectorName viewAlias = viewProjectNode.getSelectors().iterator().next();
115
116 Map<SelectorName, SelectorName> replacements = Collections.singletonMap(viewAlias, tableAliasOrName);
117 PlanUtil.replaceReferencesToRemovedSource(context, viewPlan, replacements);
118 }
119
120
121 sourceNode.addLastChild(viewPlan);
122
123
124 sourceNode.extractFromParent();
125
126
127 PlanNode parent = viewPlan.getParent();
128 if (parent != null) {
129 PlanUtil.ColumnMapping aliasMappings = null;
130 if (tableAlias != null) {
131 aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan);
132 PlanUtil.replaceViewReferences(context, parent, aliasMappings);
133 }
134 PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan);
135 PlanUtil.replaceViewReferences(context, parent, viewMappings);
136 }
137
138 if (viewPlan.is(Type.PROJECT)) {
139
140 PlanNode node = viewPlan.getParent();
141 while (node != null) {
142 if (node.isOneOf(Type.JOIN)) break;
143 if (node.is(Type.PROJECT) && viewPlan.getSelectors().containsAll(node.getSelectors())) {
144 viewPlan.extractFromParent();
145 break;
146 }
147 node = node.getParent();
148 }
149 }
150 foundViews = true;
151 }
152 }
153 } while (foundViews);
154
155 if (foundViews) {
156
157
158 if (!(ruleStack.getFirst() instanceof RaiseSelectCriteria)) {
159 ruleStack.addFirst(RaiseSelectCriteria.INSTANCE);
160 ruleStack.addFirst(PushSelectCriteria.INSTANCE);
161 }
162
163
164
165 ruleStack.addFirst(this);
166 }
167 return plan;
168 }
169
170
171
172
173
174
175 @Override
176 public String toString() {
177 return getClass().getSimpleName();
178 }
179
180 }