The catalog (class Catalog in SimpleDB) consists of a list of the tables and schemas of the tables that are currently in the database. You will need to support the ability to add a new table, as well as getting information about a particular table. Associated with each table is a TupleDesc object that allows operators to determine the types and number of fields in a table.
The global catalog is a single instance of Catalog that is allocated for the entire SimpleDB process. The global catalog can be retrieved via the method Database.getCatalog(), and the same goes for the global buffer pool (using Database.getBufferPool()).Exercise 2. Implement the skeleton methods in:
src/java/simpledb/Catalog.java
At this point, your code should pass the unit tests in CatalogTest.
这会是写好目录,这个类里头有所有的表和表的数据。代码如下
package simpledb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
/**
* The Catalog keeps track of all available tables in the database and their
* associated schemas.
* For now, this is a stub catalog that must be populated with tables by a
* user program before it can be used -- eventually, this should be converted
* to a catalog that reads a catalog table from disk.
*/
public class Catalog {
/**
* Constructor.
* Creates a new, empty catalog.
*/
private List<table> tables ;
static class table{
public DbFile dbFile;
public String name;
public String pkeyField;
public int tableId;
}
public Catalog() {
// some code goes here
tables = new ArrayList<>();
}
/**
* Add a new table to the catalog.
* This table's contents are stored in the specified DbFile.
* @param file the contents of the table to add; file.getId() is the identfier of
* this file/tupledesc param for the calls getTupleDesc and getFile
* @param name the name of the table -- may be an empty string. May not be null. If a name
* @param pkeyField the name of the primary key field
* conflict exists, use the last table to be added as the table for a given name.
*/
public void addTable(DbFile file, String name, String pkeyField) {
// some code goes here
table newtable = new table();
newtable.dbFile = file;
newtable.name = name;
newtable.pkeyField = pkeyField;
newtable.tableId = file.getId();
for (int i=0;i<tables.size();i++){
table t = tables.get(i);
if (t.name==name){
newtable.tableId = t.tableId;
tables.set(i,newtable);
return;
}
}
this.tables.add(newtable);
System.out.println(newtable);
}
public void addTable(DbFile file, String name) {
addTable(file, name, "");
}
/**
* Add a new table to the catalog.
* This table has tuples formatted using the specified TupleDesc and its
* contents are stored in the specified DbFile.
* @param file the contents of the table to add; file.getId() is the identfier of
* this file/tupledesc param for the calls getTupleDesc and getFile
*/
public void addTable(DbFile file) {
addTable(file, (UUID.randomUUID()).toString());
}
/**
* Return the id of the table with a specified name,
* @throws NoSuchElementException if the table doesn't exist
*/
public int getTableId(String name) throws NoSuchElementException {
// some code goes here
for (table t:tables){
if (t.name==name){
return t.tableId;
}
}
throw new NoSuchElementException();
}
/**
* Returns the tuple descriptor (schema) of the specified table
* @param tableid The id of the table, as specified by the DbFile.getId()
* function passed to addTable
* @throws NoSuchElementException if the table doesn't exist
*/
public TupleDesc getTupleDesc(int tableid) throws NoSuchElementException {
// some code goes here
for (table t :tables){
if (t.tableId==tableid){
return t.dbFile.getTupleDesc();
}
}
return null;
}
/**
* Returns the DbFile that can be used to read the contents of the
* specified table.
* @param tableid The id of the table, as specified by the DbFile.getId()
* function passed to addTable
*/
public DbFile getDbFile(int tableid) throws NoSuchElementException {
// some code goes here
for (table t :tables){
if (t.tableId==tableid){
return t.dbFile;
}
}
return null;
}
public String getPrimaryKey(int tableid) {
// some code goes here
for (table t :tables){
if (t.tableId==tableid){
return t.pkeyField;
}
}
return null;
}
public Iterator<Integer> tableIdIterator() {
// some code goes here
return new Iterator<Integer>() {
private int index=0;
@Override
public boolean hasNext() {
return index<tables.size();
}
@Override
public Integer next() {
int count = index;
index++;
return tables.get(count).tableId;
}
};
}
public String getTableName(int id) {
// some code goes here
for (table t :tables){
if (t.tableId==id){
return t.name;
}
}
return null;
}
/** Delete all tables from the catalog */
public void clear() {
// some code goes here
tables = new ArrayList<>();
}
/**
* Reads the schema from a file and creates the appropriate tables in the database.
* @param catalogFile
*/
public void loadSchema(String catalogFile) {
String line = "";
String baseFolder=new File(catalogFile).getParent();
try {
BufferedReader br = new BufferedReader(new FileReader(new File(catalogFile)));
while ((line = br.readLine()) != null) {
//assume line is of the format name (field type, field type, ...)
String name = line.substring(0, line.indexOf("(")).trim();
//System.out.println("TABLE NAME: " + name);
String fields = line.substring(line.indexOf("(") + 1, line.indexOf(")")).trim();
String[] els = fields.split(",");
ArrayList<String> names = new ArrayList<String>();
ArrayList<Type> types = new ArrayList<Type>();
String primaryKey = "";
for (String e : els) {
String[] els2 = e.trim().split(" ");
names.add(els2[0].trim());
if (els2[1].trim().toLowerCase().equals("int"))
types.add(Type.INT_TYPE);
else if (els2[1].trim().toLowerCase().equals("string"))
types.add(Type.STRING_TYPE);
else {
System.out.println("Unknown type " + els2[1]);
System.exit(0);
}
if (els2.length == 3) {
if (els2[2].trim().equals("pk"))
primaryKey = els2[0].trim();
else {
System.out.println("Unknown annotation " + els2[2]);
System.exit(0);
}
}
}
Type[] typeAr = types.toArray(new Type[0]);
String[] namesAr = names.toArray(new String[0]);
TupleDesc t = new TupleDesc(typeAr, namesAr);
HeapFile tabHf = new HeapFile(new File(baseFolder+"/"+name + ".dat"), t);
addTable(tabHf,name,primaryKey);
System.out.println("Added table : " + name + " with schema " + t);
}
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
} catch (IndexOutOfBoundsException e) {
System.out.println ("Invalid catalog entry : " + line);
System.exit(0);
}
}
}
这个可以还是不可以通过测试,因为我前面的TupleDesc出了点问题,导致第一个test过不了,就是equals方法出了个问题,得补上TDItem的equals方法
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 + ")";
}
@Override
public boolean equals(Object obj) {
if(obj==null)return false;
if (obj==this)return true;
if (getClass() !=obj.getClass()){
return false;
}
TDItem tdItem = (TDItem) obj;
return tdItem.fieldName.equals(this.fieldName)&&tdItem.fieldType.equals(this.fieldType);
}
}
这样三个测试都可以过了。