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.process;
25
26 import java.util.ArrayList;
27 import java.util.Comparator;
28 import java.util.Iterator;
29 import java.util.List;
30 import net.jcip.annotations.Immutable;
31 import org.modeshape.graph.Location;
32 import org.modeshape.graph.query.QueryContext;
33 import org.modeshape.graph.query.QueryResults.Columns;
34 import org.modeshape.graph.query.model.ChildNodeJoinCondition;
35 import org.modeshape.graph.query.model.EquiJoinCondition;
36 import org.modeshape.graph.query.model.JoinType;
37 import org.modeshape.graph.query.model.SameNodeJoinCondition;
38
39
40
41
42
43
44
45
46
47
48 @Immutable
49 public class MergeJoinComponent extends JoinComponent {
50
51 public MergeJoinComponent( QueryContext context,
52 ProcessingComponent left,
53 ProcessingComponent right,
54 EquiJoinCondition condition,
55 JoinType joinType ) {
56 super(context, left, right, condition, joinType);
57 }
58
59 public MergeJoinComponent( QueryContext context,
60 ProcessingComponent left,
61 ProcessingComponent right,
62 ChildNodeJoinCondition condition,
63 JoinType joinType ) {
64 super(context, left, right, condition, joinType);
65 }
66
67 public MergeJoinComponent( QueryContext context,
68 ProcessingComponent left,
69 ProcessingComponent right,
70 SameNodeJoinCondition condition,
71 JoinType joinType ) {
72 super(context, left, right, condition, joinType);
73 }
74
75
76
77
78
79
80 @Override
81 public List<Object[]> execute() {
82
83 final Columns leftColumns = left().getColumns();
84 final Columns rightColumns = right().getColumns();
85 final ValueSelector leftSelector = valueSelectorFor(left(), getJoinCondition());
86 final ValueSelector rightSelector = valueSelectorFor(right(), getJoinCondition());
87 final Comparator<Object> comparator = comparatorFor(getContext(), left(), right(), getJoinCondition());
88 final TupleMerger merger = createMerger(getColumns(), leftColumns, rightColumns);
89
90
91 List<Object[]> leftTuples = left().execute();
92 List<Object[]> rightTuples = right().execute();
93 List<Object[]> tuples = new ArrayList<Object[]>(leftTuples.size() * rightTuples.size());
94 Iterator<Object[]> leftIter = leftTuples.iterator();
95 Iterator<Object[]> rightIter = rightTuples.iterator();
96 Object[] leftTuple = leftIter.next();
97 Object[] rightTuple = rightIter.next();
98 Object[] nextLeftTuple = null;
99 Object[] nextRightTuple = null;
100 while (true) {
101
102 Object leftValue = leftSelector.evaluate(leftTuple);
103 Object rightValue = rightSelector.evaluate(rightTuple);
104
105 int compare = comparator.compare(leftValue, rightValue);
106 while (compare == 0) {
107 Object[] result = merger.merge(leftTuple, rightTuple);
108 tuples.add(result);
109
110
111 if (nextRightTuple == null) {
112 nextRightTuple = rightIter.next();
113 while (isSameTuple(rightColumns, nextRightTuple, rightTuple)) {
114 nextRightTuple = rightIter.next();
115 }
116 }
117
118
119 leftValue = leftSelector.evaluate(leftTuple);
120 rightValue = rightSelector.evaluate(nextRightTuple);
121 compare = comparator.compare(leftValue, rightValue);
122 if (compare == 0) {
123
124 rightTuple = nextRightTuple;
125 nextRightTuple = null;
126 continue;
127 }
128 if (compare > 0) {
129
130 rightTuple = nextRightTuple;
131 nextRightTuple = null;
132 compare = 0;
133 break;
134 }
135
136
137
138 nextLeftTuple = leftIter.next();
139 while (isSameTuple(leftColumns, nextLeftTuple, leftTuple)) {
140 nextLeftTuple = leftIter.next();
141 }
142 leftValue = leftSelector.evaluate(nextLeftTuple);
143 rightValue = rightSelector.evaluate(rightTuple);
144 compare = comparator.compare(leftValue, rightValue);
145 if (compare == 0) {
146
147 leftTuple = nextLeftTuple;
148 nextLeftTuple = null;
149 continue;
150 }
151
152
153 leftTuple = nextLeftTuple;
154 rightTuple = nextRightTuple;
155 nextLeftTuple = null;
156 nextRightTuple = null;
157 compare = 0;
158 break;
159 }
160
161 if (compare < 0) {
162
163 if (!leftIter.hasNext()) break;
164 leftTuple = leftIter.next();
165 }
166 if (compare > 0) {
167
168 if (!rightIter.hasNext()) break;
169 rightTuple = rightIter.next();
170 }
171 }
172 return tuples;
173 }
174
175 protected final boolean isSameTuple( Columns columns,
176 Object[] tuple1,
177 Object[] tuple2 ) {
178 for (int i = columns.getColumnCount(); i != columns.getLocationCount(); ++i) {
179 Location location = (Location)tuple1[i];
180 Location location2 = (Location)tuple2[i];
181 if (!location.isSame(location2)) return false;
182 }
183 return true;
184 }
185 }