-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathJoin.java
More file actions
141 lines (122 loc) · 4 KB
/
Copy pathJoin.java
File metadata and controls
141 lines (122 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package simpledb;
import java.util.*;
/**
* The Join operator implements the relational join operation.
*/
public class Join extends Operator {
private static final long serialVersionUID = 1L;
private final JoinPredicate predicate;
private final TupleDesc td;
private DbIterator child1;
private DbIterator child2;
private Tuple tuple1;
/**
* Constructor. Accepts to children to join and the predicate to join them
* on
*
* @param predicate
* The predicate to use to join the children
* @param child1
* Iterator for the left(outer) relation to join
* @param child2
* Iterator for the right(inner) relation to join
*/
public Join(JoinPredicate predicate, DbIterator child1, DbIterator child2) {
this.predicate = predicate;
this.child1 = child1;
this.child2 = child2;
td = TupleDesc.merge(child1.getTupleDesc(), child2.getTupleDesc());
}
public JoinPredicate getJoinPredicate() {
return predicate;
}
/**
* @return
* the field name of join field1. Should be quantified by
* alias or table name.
* */
public String getJoinField1Name() {
return child1.getTupleDesc().getFieldName(predicate.getField1());
}
/**
* @return
* the field name of join field2. Should be quantified by
* alias or table name.
* */
public String getJoinField2Name() {
return child2.getTupleDesc().getFieldName(predicate.getField2());
}
/**
* @see simpledb.TupleDesc#merge(TupleDesc, TupleDesc) for possible
* implementation logic.
*/
public TupleDesc getTupleDesc() {
return td;
}
@Override
public void open() throws DbException, NoSuchElementException,
TransactionAbortedException {
super.open();
child1.open();
child2.open();
tuple1 = null;
}
@Override
public void close() {
super.close();
child1.close();
child2.close();
tuple1 = null;
}
public void rewind() throws DbException, TransactionAbortedException {
close();
open();
}
/**
* Returns the next tuple generated by the join, or null if there are no
* more tuples. Logically, this is the next tuple in r1 cross r2 that
* satisfies the join predicate. There are many possible implementations;
* the simplest is a nested loops join.
* <p>
* Note that the tuples returned from this particular implementation of Join
* are simply the concatenation of joining tuples from the left and right
* relation. Therefore, if an equality predicate is used there will be two
* copies of the join attribute in the results. (Removing such duplicate
* columns can be done with an additional projection operator if needed.)
* <p>
* For example, if one tuple is {1,2,3} and the other tuple is {1,5,6},
* joined on equality of the first column, then this returns {1,2,3,1,5,6}.
*
* @return The next matching tuple.
* @see JoinPredicate#filter
*/
protected Tuple fetchNext() throws TransactionAbortedException, DbException {
while (true) {
if (tuple1 == null) {
if (child1.hasNext()) {
tuple1 = child1.next();
child2.rewind();
} else {
return null;
}
}
while (child2.hasNext()) {
Tuple tuple2 = child2.next();
if (predicate.filter(tuple1, tuple2)) {
return Tuple.merge(tuple1, tuple2);
}
}
tuple1 = null;
}
}
@Override
public DbIterator[] getChildren() {
return new DbIterator[]{child1, child2};
}
@Override
public void setChildren(DbIterator[] children) {
assert children.length == 2;
child1 = children[0];
child2 = children[1];
}
}