Author: Sixing Yan
在SimpleDB-2.10中,数据库系统仅支持Int型和String型数据,即创建的schema仅支持 int 和 varchar 类型的数据。在SimpleDB-3.0中,我们增加了对FLOAT型数据的支持。
1. Constant
在SimpleDB中,存储的数据都是Constant型的数据,即都实现了Constant 这个接口。而Int和String数据则被实现为 IntConstant 类和 StringConstant 类。观察Constant接口以及IntConstant类的代码,我们可以实现float型数据类,即FloatConstant 类。
package simpledb.query;
/**
* The class that wraps Java floats as database constants.
* @author Sixing Yan
*/
public class FloatConstant implements Constant {
private float val;
public FloatConstant(float n) {val = n;}
public Object asJavaVal() {return val;}
public boolean equals(Object obj) {
FloatConstant ic = (FloatConstant) obj;
return ic != null && val.equals(ic.val);}
public int compareTo(Constant c) {
FloatConstant ic = (FloatConstant) c;
return val.compareTo(ic.val);}
public int hashCode() {return val.hashCode();}
public String toString() {return val.toString();}
}
增加后float类的SimpleDB实现后,我们还要相应地让SimpleDB的Schema功能、Parse功能和Lexer功能支持float类。其中Schema功能与表的结构相关,Parse功能与SQL执行命令相关, Lexer功能与SQL语法解析相关。
2. Schema
对于Schema功能(类),增加AddFloatField方法。 这里我们设计语句只支持 float 而不支持 float(b) 这样的语法,因为 float(b) 的参数 b 指代二进制进度,而不是一般意义上的小数点精度,这样的含义容易让一般用户迷惑。所以这里只简单的实现 float。
FLOAT(b) specifies a floating-point number with binary precision b. The precision b can range from 1 to 126. To convert from binary to decimal precision, multiply b by 0.30103. ---Oracle Online Help
public class Schema {
...
/**
* Adds an float field to the schema.
* @param fldname the name of the field
*/
public void addFloatField(String fldname) {addField(fldname, FLOAT, 0); }
...
}
3.Parse
对于Perse功能(类),增加对“float”关键字的判断。如果有,则对schema添加Float类型的数据。
public class Parser {
...
public Constant constant() {
if (lex.matchStringConstant())
return new StringConstant(lex.eatStringConstant());
else if (lex.matchFloatConstant())
return new FloatConstant(lex.eatFloatConstant());
else
return new IntConstant(lex.eatIntConstant());
}
/**
* Returns true if both of the term's expressions
* evaluate to the same constant,
* Only work with 'primary key'
* @param fldname the scan
* @return true if both expressions have the same value in the scan
*/
private Schema fieldType(String fldname) {
Schema schema = new Schema();
if (lex.matchKeyword("int")) {
...
} else if (lex.matchKeyword("varchar")) {
...
} else {
lex.eatKeyword("float");
int strLen = lex.eatFloatConstant();
schema.addFloatField(fldname, strLen);
}
return schema;}
...
}
4. Lexer
对于Lexer功能(类),增加对“float”型数据的检查和抽取。Lexer主要通过检测是否匹配,与抽取该位置的数值两部分组成,方法名为matchXXX() 和 eatXXX(),例如matchId和eatId等方法。其中matchFloatConstant只需判断当前数值是否为数字,而eatFloatConstant将输入的字符串转换成float型数据即可。
public class Lexer {
...
/**
* Returns true if the current token is a number.
* @return true if the current token is a number
*/
public boolean matchFloatConstant() {
return tok.ttype == StreamTokenizer.TT_NUMBER;
}
/**
* Throws an exception if the current token is not a float.
* Otherwise, returns that string and moves to the next token.
* @return the string value of the current token
*/
public float eatFloatConstant() {
if (!matchFloatConstant()) throw new BadSyntaxException();
float i = new Float(tok.nval);
nextToken();
return i;}
...
private void initKeywords() { keywords = Arrays.asList(..., "float", ...);}
}