我一般不把他写的todo去掉,万一以后改防止改错了。前两个主要实现filter方法,因为后面要用
先放上Predicate.java
package simpledb;
import java.io.Serializable;
/**
* Predicate compares tuples to a specified Field value.
*/
public class Predicate implements Serializable {
private static final long serialVersionUID = 1L;
int field;
Op op;
Field operand;
/** Constants used for return codes in Field.compare */
public enum Op implements Serializable {
EQUALS, GREATER_THAN, LESS_THAN, LESS_THAN_OR_EQ, GREATER_THAN_OR_EQ, LIKE, NOT_EQUALS;
/**
* Interface to access operations by a string containing an integer
* index for command-line convenience.
*
* @param s
* a string containing a valid integer Op index
*/
public static Op getOp(String s) {
return getOp(Integer.parseInt(s));
}
/**
* Interface to access operations by integer value for command-line
* convenience.
*
* @param i
* a valid integer Op index
*/
public static Op getOp(int i) {
return values()[i];
}
public String toString() {
if (this == EQUALS)
return "=";
if (this == GREATER_THAN)
return ">";
if (this == LESS_THAN)
return "<";
if (this == LESS_THAN_OR_EQ)
return "<=";
if (this == GREATER_THAN_OR_EQ)
return ">=";
if (this == LIKE)
return "like";
if (this == NOT_EQUALS)
return "<>";
throw new IllegalStateException("impossible to reach here");
}
}
/**
* Constructor.
*
* @param field
* field number of passed in tuples to compare against.
* @param op
* operation to use for comparison
* @param operand
* field value to compare passed in tuples to
*/
public Predicate(int field, Op op, Field operand) {
// some code goes here
this.field = field;
this.op = op;
this.operand = operand;
}
/**
* @return the field number
*/
public int getField()
{
// some code goes here
return field;
}
/**
* @return the operator
*/
public Op getOp()
{
// some code goes here
return op;
}
/**
* @return the operand
*/
public Field getOperand()
{
// some code goes here
return operand;
}
/**
* Compares the field number of t specified in the constructor to the
* operand field specified in the constructor using the operator specific in
* the constructor. The comparison can be made through Field's compare
* method.
*
* @param t
* The tuple to compare against
* @return true if the comparison is true, false otherwise.
*/
public boolean filter(Tuple t) {
// some code goes here
return t.getField(field).compare(op,operand);
}
/**
* Returns something useful, like "f = field_id op = op_string operand =
* operand_string
*/
public String toString() {
return ""+"field = "+field+" op = "+op.toString()+" operand"+operand.toString();
}
}
再放上JoinPredicate
package simpledb;
import java.io.Serializable;
/**
* JoinPredicate compares fields of two tuples using a predicate. JoinPredicate
* is most likely used by the Join operator.
*/
public class JoinPredicate implements Serializable {
private static final long serialVersionUID = 1L;
Predicate.Op op;
int field1;
int field2;
/**
* Constructor -- create a new predicate over two fields of two tuples.
*
* @param field1
* The field index into the first tuple in the predicate
* @param field2
* The field index into the second tuple in the predicate
* @param op
* The operation to apply (as defined in Predicate.Op); either
* Predicate.Op.GREATER_THAN, Predicate.Op.LESS_THAN,
* Predicate.Op.EQUAL, Predicate.Op.GREATER_THAN_OR_EQ, or
* Predicate.Op.LESS_THAN_OR_EQ
* @see Predicate
*/
public JoinPredicate(int field1, Predicate.Op op, int field2) {
// some code goes here
this.field1 = field1;
this.field2 = field2;
this.op = op;
}
/**
* Apply the predicate to the two specified tuples. The comparison can be
* made through Field's compare method.
*
* @return true if the tuples satisfy the predicate.
*/
public boolean filter(Tuple t1, Tuple t2) {
// some code goes here
return t1.getField(field1).compare(op,t2.getField(field2));
}
public int getField1()
{
// some code goes here
return field1;
}
public int getField2()
{
// some code goes here
return field2;
}
public Predicate.Op getOperator()
{
// some code goes here
return op;
}
}
Filter.java
package simpledb;
import java.util.*;
/**
* Filter is an operator that implements a relational select.
*/
public class Filter extends Operator {
private static final long serialVersionUID = 1L;
Predicate p;
DbIterator child;
/**
* Constructor accepts a predicate to apply and a child operator to read
* tuples to filter from.
*
* @param p
* The predicate to filter tuples with
* @param child
* The child operator
*/
public Filter(Predicate p, DbIterator child) {
// some code goes here
this.p = p;
this.child = child;
}
public Predicate getPredicate() {
// some code goes here
return p;
}
public TupleDesc getTupleDesc() {
// some code goes here
return child.getTupleDesc();
}
public void open() throws DbException, NoSuchElementException,
TransactionAbortedException {
super.open();
child.open();
}
public void close() {
// some code goes here
try {
super.open();
} catch (DbException e) {
e.printStackTrace();
} catch (TransactionAbortedException e) {
e.printStackTrace();
}
child.close();
}
public void rewind() throws DbException, TransactionAbortedException {
// some code goes here
super.open();
child.rewind();
}
/**
* AbstractDbIterator.readNext implementation. Iterates over tuples from the
* child operator, applying the predicate to them and returning those that
* pass the predicate (i.e. for which the Predicate.filter() returns true.)
*
* @return The next tuple that passes the filter, or null if there are no
* more tuples
* @see Predicate#filter
*/
protected Tuple fetchNext() throws NoSuchElementException,
TransactionAbortedException, DbException {
// some code goes here
while (child.hasNext()){
Tuple tuple = child.next();
if(p.filter(tuple)){
return tuple;
}
}
return null;
}
@Override
public DbIterator[] getChildren() {
// some code goes here
return new DbIterator[]{child};
}
@Override
public void setChildren(DbIterator[] children) {
// some code goes here
}
}
最后Join.java,
this.scan1 = TestUtil.createTupleList(width1,
new int[] { 1, 2,
3, 4,
5, 6,
7, 8 });
this.scan2 = TestUtil.createTupleList(width2,
new int[] { 1, 2, 3,
2, 3, 4,
3, 4, 5,
4, 5, 6,
5, 6, 7 });
this.eqJoin = TestUtil.createTupleList(width1 + width2,
new int[] { 1, 2, 1, 2, 3,
3, 4, 3, 4, 5,
5, 6, 5, 6, 7 });
this.gtJoin = TestUtil.createTupleList(width1 + width2,
new int[] {
3, 4, 1, 2, 3, // 1, 2 < 3
3, 4, 2, 3, 4,
5, 6, 1, 2, 3, // 1, 2, 3, 4 < 5
5, 6, 2, 3, 4,
5, 6, 3, 4, 5,
5, 6, 4, 5, 6,
7, 8, 1, 2, 3, // 1, 2, 3, 4, 5 < 7
7, 8, 2, 3, 4,
7, 8, 3, 4, 5,
7, 8, 4, 5, 6,
7, 8, 5, 6, 7 });
上面是测试的代码,可以让你弄懂等于连接,和大于连接是怎么回事
然后就可以开始写代码了
package simpledb;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The Join operator implements the relational join operation.
*/
public class Join extends Operator {
JoinPredicate p;
TupleDesc tupleDesc;
DbIterator child1;
DbIterator child2;
Tuple tuple1;
Tuple tuple2;
private static final long serialVersionUID = 1L;
/**
* Constructor. Accepts to children to join and the predicate to join them
* on
*
* @param p 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 p, DbIterator child1, DbIterator child2) {
// some code goes here
this.p = p;
tupleDesc = TupleDesc.merge(child1.getTupleDesc(), child2.getTupleDesc());
this.child2 = child2;
this.child1 = child1;
//必须用类似克隆的方法
}
public JoinPredicate getJoinPredicate() {
// some code goes here
return p;
}
/**
* @return the field name of join field1. Should be quantified by
* alias or table name.
*/
public String getJoinField1Name() {
// some code goes here
return tupleDesc.getFieldName(p.field1);
}
/**
* @return the field name of join field2. Should be quantified by
* alias or table name.
*/
public String getJoinField2Name() {
// some code goes here
return tupleDesc.getFieldName(p.field2);
}
/**
* @see simpledb.TupleDesc#merge(TupleDesc, TupleDesc) for possible
* implementation logic.
*/
public TupleDesc getTupleDesc() {
// some code goes here
return tupleDesc;
}
public void open() throws DbException, NoSuchElementException,
TransactionAbortedException {
// some code goes here
super.open();
child1.open();
child2.open();
}
public void close() {
// some code goes here
super.close();
child2.close();
child1.close();
}
public void rewind() throws DbException, TransactionAbortedException {
// some code goes here
super.rewind();
child2.rewind();
child1.rewind();
}
// @Override
// public boolean hasNext() throws DbException, TransactionAbortedException {
// return super.hasNext();
// }
/**
* 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 {
// some code goes here
if (tuple1 == null && child1.hasNext())
tuple1 = child1.next();
while (tuple1 != null) {
while (child2.hasNext()) {
tuple2 = child2.next();
if (p.filter(tuple1, tuple2)) {
Tuple newTuple = new Tuple(getTupleDesc());
Iterator<Field> iterator = tuple1.fields();
int i = 0;
while (iterator.hasNext()) {
newTuple.setField(i++, iterator.next());
}
iterator = tuple2.fields();
while (iterator.hasNext()) {
newTuple.setField(i++, iterator.next());
}
//child2.rewind();
return newTuple;
}
}
child2.rewind();
if (child1.hasNext()) {
tuple1 = child1.next();
}else return null;
}
return null;
}
@Override
public DbIterator[] getChildren() {
// some code goes here
return new DbIterator[]{child1, child2};
}
@Override
public void setChildren(DbIterator[] children) {
// some code goes here
if (children.length != 2) return;
child1 = children[0];
child2 = children[1];
}
}