0304: 其他SQL语句

其他语句

仿照上一步的 parseSelect(),增加一些语句:

create table t (
    a int64,
    b string,
    c string,
    primary key (b, c)
);
insert into t values (1, 'x', 'y');
update t set a = 1 where b = 'x' and c = 'y';
delete from t where b = 'x' and c = 'y';

对应的类型:

type StmtCreatTable struct {
    table string
    cols  []Column
    pkey  []string
}
type StmtInsert struct {
    table string
    value []Cell
}
type StmtUpdate struct {
    table string
    keys  []NamedCell
    value []NamedCell
}
type StmtDelete struct {
    table string
    keys  []NamedCell
}

现在只实现了通过主键来操作单个 row,所以 WHERE 部分对应 keys。以后会增加范围查询、索引,相应的语法也会更复杂。

判断SQL语句

增加 parseStmt() 函数,用 interface{} 来返回不同的语句类型:

func (p *Parser) parseStmt() (out interface{}, err error) {
    if p.tryKeyword("SELECT") {
        stmt := &StmtSelect{}
        err = p.parseSelect(stmt)
        out = stmt
    } else if p.tryKeyword("CREATE", "TABLE") {
        stmt := &StmtCreatTable{}
        err = p.parseCreateTable(stmt)
        out = stmt
    } else if p.tryKeyword("INSERT", "INTO") {
        stmt := &StmtInsert{}
        err = p.parseInsert(stmt)
        out = stmt
    } else if p.tryKeyword("UPDATE") {
        stmt := &StmtUpdate{}
        err = p.parseUpdate(stmt)
        out = stmt
    } else if p.tryKeyword("DELETE", "FROM") {
        stmt := &StmtDelete{}
        err = p.parseDelete(stmt)
        out = stmt
    } else {
        err = errors.New("unknown statement")
    }
    if err != nil {
        return nil, err
    }
    return out, nil
}

其中 tryKeyword() 函数修改成了循环匹配多个 token:

func (p *Parser) tryKeyword(kws ...string) bool

既然 parseStmt() 里已经把开头的 token 消耗掉了,所以之前的 parseSelect() 要修改。

这一步可以看到,解析SQL时,只要看当前的1~2个 token 就能决定下一步怎么做。很多计算机语言解析起来都是这么容易,并不需要编译原理里复杂的理论。即使以后增加了 select a+b*c 这样复杂的语法,也只要会用递归就行了。