2.2. Fields and Tuples
Tuples in SimpleDB are quite basic. They consist of a collection of Field objects, one per field in the Tuple. Field is an interface that different data types (e.g., integer, string) implement. Tuple objects are created by the underlying access methods (e.g., heap files, or B-trees), as described in the next section. Tuples also have a type (or schema), called a tuple descriptor, represented by a TupleDesc object. This object consists of a collection of Type objects, one per field in the tuple, each of which describes the type of the corresponding field.
Exercise 1. Implement the skeleton methods in:
src/java/simpledb/TupleDesc.java
src/java/simpledb/Tuple.java
At this point, your code should pass the unit tests TupleTest and TupleDescTest. At this point, modifyRecordId() should fail because you havn’t implemented it yet.
这门课给的代码框架资料可以在我上传的资料库里找,需要数据库基础
这是TupleDesc.java的代码,用来描述元组模式,补全代码靠它的说明就能打出来,后期靠调试补全。
package simpledb;
import java.io.Serializable;
import java.util.*;
/**
* TupleDesc describes the schema of a tuple.元组的模式
*/
public class TupleDesc implements Serializable, Iterable<TupleDesc.TDItem> {
/**
* A help class to facilitate organizing the information of each field
*/
private List tdItems = new ArrayList<>();
public TupleDesc(){
}
public static class TDItem implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The type of the field
*/
Type fieldType;
/**
* The name of the field
*/
String fieldName;
public TDItem(Type t, String n) {
this.fieldName = n;
this.fieldType = t;
}
public String toString() {
return fieldName + "(" + fieldType + ")";
}
}
/**
* @return An iterator which iterates over all the field TDItems
* that are included in this TupleDesc
*/
/*使用了继承Iterable方法*/
@Override
public Iterator iterator() {
// some code goes here
if (tdItems.size() > 0) {
return new Iterator() {
private Integer index = 0;
@Override
public boolean hasNext() {
return index < tdItems.size();
}
@Override
public TDItem next() {
int num = index;
index++;
return tdItems.get(num);
}
};
}else {
return null;
}
}
private static final long serialVersionUID = 1L;
/**
* Create a new TupleDesc with typeAr.length fields with fields of the
* specified types, with associated named fields.
*
* @param typeAr array specifying the number of and types of fields in this
* TupleDesc. It must contain at least one entry.
* @param fieldAr array specifying the names of the fields. Note that names may
* be null.
*/
public TupleDesc(Type[] typeAr, String[] fieldAr) {
// some code goes here
int len =0;
if (typeAr.length!=fieldAr.length) {System.out.println("数据不符");return;}
len = typeAr.length;
for (int i=0;inew TDItem(typeAr[i],fieldAr[i]);
this.tdItems.add(newtd);
}
}
/**
* Constructor. Create a new tuple desc with typeAr.length fields with
* fields of the specified types, with anonymous (unnamed) fields.
*
* @param typeAr array specifying the number of and types of fields in this
* TupleDesc. It must contain at least one entry.
*/
public TupleDesc(Type[] typeAr) {
/*当没名字给予默认名字unname+数字序号*/
String unname = "unname";
for (int i=0;inew TDItem(typeAr[i],unname+i);
this.tdItems.add(newtd);
}
// some code goes here
}
/**
* @return the number of fields in this TupleDesc
*/
public int numFields() {
// some code goes here
int count = 0;
/*判断类是否相等*/
for (TDItem tdItem:tdItems){
if (tdItem.fieldType==Type.INT_TYPE){
count++;
}
}
return count;
}
/**
* Gets the (possibly null) field name of the ith field of this TupleDesc.
*
* @param i index of the field name to return. It must be a valid index.
* @return the name of the ith field
* @throws NoSuchElementException if i is not a valid field reference.
*/
public String getFieldName(int i) throws NoSuchElementException {
if (i>=0&&i<this.tdItems.size()){
return this.tdItems.get(i).fieldName;
}
return null;
}
/**
* Gets the type of the ith field of this TupleDesc.
*
* @param i The index of the field to get the type of. It must be a valid
* index.
* @return the type of the ith field
* @throws NoSuchElementException if i is not a valid field reference.
*/
public Type getFieldType(int i) throws NoSuchElementException {
// some code goes here
if (i>=0&&i<this.tdItems.size()){
return this.tdItems.get(i).fieldType;
}
return null;
}
/**
* Find the index of the field with a given name.
*
* @param name name of the field.
* @return the index of the field that is first to have the given name.
* @throws NoSuchElementException if no field with a matching name is found.
*/
public int fieldNameToIndex(String name) throws NoSuchElementException {
// some code goes here
for (int i=0;i<this.tdItems.size();i++){
if (this.tdItems.get(i).fieldName.equals(name))return i;
}
throw new NoSuchElementException ();
}
/**
* @return The size (in bytes) of tuples corresponding to this TupleDesc.
* Note that tuples from a given TupleDesc are of a fixed size.
*/
public int getSize() {
int count=0;
for (int i=0;iif (tdItems.get(i).fieldType==Type.INT_TYPE){
count+=Type.INT_TYPE.getLen();
}else{
count+=Type.STRING_TYPE.getLen();
}
}
return count;
}
/**
* Merge two TupleDescs into one, with td1.numFields + td2.numFields fields,
* with the first td1.numFields coming from td1 and the remaining from td2.
*
* @param td1 The TupleDesc with the first fields of the new TupleDesc
* @param td2 The TupleDesc with the last fields of the TupleDesc
* @return the new TupleDesc
*/
public static TupleDesc merge(TupleDesc td1, TupleDesc td2) {
// some code goes here
//这个没真的数据库那么复杂的连接,不考虑重复,直接完全链接
TupleDesc tupleDesc = new TupleDesc();
int len1 = td1.tdItems.size();
int len2 = td2.tdItems.size();
for (int i=0;ifor (int i = 0;ireturn tupleDesc;
}
/**
* Compares the specified object with this TupleDesc for equality. Two
* TupleDescs are considered equal if they are the same size and if the n-th
* type in this TupleDesc is equal to the n-th type in td.
*
* @param o the Object to be compared for equality with this TupleDesc.
* @return true if the object is equal to this TupleDesc.
*/
public boolean equals(Object o) {
// some code goes here
if(o==null)return false;
if (o==this)return true;
if (getClass() !=o.getClass()){
return false;
}
TupleDesc tupleDesc = (TupleDesc)o;
return tupleDesc.tdItems.equals(this.tdItems);
}
public int hashCode() {
// If you want to use TupleDesc as keys for HashMap, implement this so
// that equal objects have equals hashCode() results
throw new UnsupportedOperationException("unimplemented");
}
/**
* Returns a String describing this descriptor. It should be of the form
* "fieldType[0](fieldName[0]), ..., fieldType[M](fieldName[M])", although
* the exact format does not matter.
*
* @return String describing this descriptor.
*/
public String toString() {
// some code goes here
StringBuilder stringBuilder = new StringBuilder();
for (int i=0;i",");
stringBuilder.append(" ");
}
return stringBuilder.toString();
}
}
这个是RecordId.java,重点重写equals方法,和hashcode方法,也是单独写,
package simpledb;
import java.io.Serializable;
/**
* A RecordId is a reference to a specific tuple on a specific page of a
* specific table.
*/
public class RecordId implements Serializable {
private static final long serialVersionUID = 1L;
private PageId pid ;
private int tupleno;
public RecordId(){
pid = new PageId() {
@Override
public int[] serialize() {
return new int[0];
}
@Override
public int getTableId() {
return 0;
}
@Override
public int pageNumber() {
return 0;
}
};
tupleno = 0;
}
/**
* Creates a new RecordId referring to the specified PageId and tuple
* number.
*
* @param pid
* the pageid of the page on which the tuple resides
* @param tupleno
* the tuple number within the page.
*/
public RecordId(PageId pid, int tupleno) {
// some code goes here
this.pid = pid;
this.tupleno = tupleno;
}
/**
* @return the tuple number this RecordId references.
*/
public int tupleno() {
// some code goes here
return tupleno;
}
/**
* @return the page id this RecordId references.
*/
public PageId getPageId() {
// some code goes here
return pid;
}
/**
* Two RecordId objects are considered equal if they represent the same
* tuple.
*
* @return True if this and o represent the same tuple
*/
@Override
public boolean equals(Object o) {
// some code goes here
if(o==null)return false;
if (o==this)return true;
if (getClass() !=o.getClass()){
return false;
}
RecordId recordId = (RecordId)o ;
return recordId.tupleno==this.tupleno&&recordId.pid.equals(recordId.pid);
//throw new UnsupportedOperationException("implement this");
}
/**
* You should implement the hashCode() so that two equal RecordId instances
* (with respect to equals()) have the same hashCode().
*
* @return An int that is the same for equal RecordId objects.
*/
@Override
public int hashCode() {//随便写的,这里算法还没研究透彻。
int result = 17;
return 17*37+this.pid.hashCode()+tupleno;
}
}
这是tuple.java的文件是建立在补全完Recordid.java和TupleDesc.java的基础上写的
package simpledb;
import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
/**
* Tuple maintains information about the contents of a tuple. Tuples have a
* specified schema specified by a TupleDesc object and contain Field objects
* with the data for each field.
*/
public class Tuple implements Serializable {
public List tuple = new ArrayList<>();
TupleDesc myTupleDesc = new TupleDesc();
RecordId recordId = new RecordId();
private static final long serialVersionUID = 1L;
/**
* Create a new tuple with the specified schema (type).
*
* @param td the schema of this tuple. It must be a valid TupleDesc
* instance with at least one field.
*/
public Tuple(TupleDesc td) {
// some code goes here 知道了属性名,根据属性名是字符串,还是整数来输入默认值
myTupleDesc = td;
System.out.println(""+myTupleDesc.toString());
int i=-1;
Iterator myTDItem = td.iterator();
while (myTDItem.hasNext()) {
TupleDesc.TDItem newTd = myTDItem.next();
if (newTd.fieldType == Type.INT_TYPE) {
tuple.add(new IntField(0));
} else {
tuple.add(new StringField("null", 255));
}
}
}
/**
* @return The TupleDesc representing the schema of this tuple.
*/
public TupleDesc getTupleDesc() {
// some code goes here
return myTupleDesc;
}
/**
* @return The RecordId representing the location of this tuple on disk. May
* be null.
*/
public RecordId getRecordId() {
// some code goes here
return this.recordId;
}
/**
* Set the RecordId information for this tuple.
*
* @param rid the new RecordId for this tuple.
*/
public void setRecordId(RecordId rid) {
// some code goes here
this.recordId = rid;
}
/**
* Change the value of the ith field of this tuple.
*
* @param i index of the field to change. It must be a valid index.
* @param f new value for the field.
*/
public void setField(int i, Field f) {
// some code goes here
if (i >= 0 && i < this.tuple.size()) {
this.tuple.set(i, f);
}
}
/**
* @param i field index to return. Must be a valid index.
* @return the value of the ith field, or null if it has not been set.
*/
public Field getField(int i) {
// some code goes here
if (i >= 0 && i < this.tuple.size()) {
return this.tuple.get(i);
}
return null;
}
/**
* Returns the contents of this Tuple as a string. Note that to pass the
* system tests, the format needs to be as follows:
*
* column1\tcolumn2\tcolumn3\t...\tcolumnN\n
*
* where \t is any whitespace, except newline, and \n is a newline
*/
public String toString() {
// some code goes here
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < this.tuple.size(); i++) {
stringBuilder.append(tuple.get(i).toString());
stringBuilder.append("\t");
}
//throw new UnsupportedOperationException("Implement this");
return stringBuilder.toString();
}
/**
* @return An iterator which iterates over all the fields of this tuple
*/
public Iterator fields() {
// some code goes here
if (tuple.size() > 0) {
return new Iterator() {
private int index = 0;
@Override
public boolean hasNext() {
return index@Override
public Field next() {
int count = index;
index++;
return tuple.get(count);
}
};
}
else return null;
}
}