0501: 中缀表达式

用树型结构来表示任意表达式

要让 SQL 支持上一步增加的范围查询功能,就要解析更复杂的语法。之前只能解析这种固定形式的 WHERE

select a, b from t where a = 123 and b = 456;

现在要支持这种形式:

select a, b from t where a > 123;
select a, b from t where (a, b) > (123, 0);

需要用数据结构来表示 WHERE 中的各种表达式(expression):

type ExprBinOp struct {
    op    ExprOp
    left  interface{}
    right interface{}
}

比如:

// a = 123 and b = 456
ExprBinOp{op: OP_AND,
    left:  &ExprBinOp{op: OP_EQ,
        left: "a",
        right: &Cell{Type: TypeI64, I64: 123}},
    right: &ExprBinOp{op: OP_EQ,
        left: "b",
        right: &Cell{Type: TypeI64, I64: 456}}}
// a > 123
ExprBinOp{op: OP_GT,
    left:  "a",
    right: &Cell{Type: TypeI64, I64: 123}}

interface{} 可以引用任意数据类型,相当于C/C++里的 void *,但带有类型信息,可以判断并转换回原始类型。这里用到3种类型:

解析中缀表达式

这一步先不考虑运算优先级,解析只包含 +- 号的表达式:

// a
"a"
// a + b
&ExprBinOp{op: OP_ADD, left: "a", right: "b"}
// a + b - 3
&ExprBinOp{op: OP_SUB,
    left:  &ExprBinOp{op: OP_ADD, left: "a", right: "b"},
    right: &Cell{Type: TypeI64, I64: 123}}

操作的对象包括列名和常数,返回 interface{}

func (p *Parser) parseAtom() (interface{}, error) {
    if name, ok := p.tryName(); ok {
        return name, nil
    }
    cell := &Cell{}
    if err := p.parseValue(cell); err != nil {
        return nil, err
    }
    return cell, nil
}

实现 parseAdd() 函数,循环调用 parseAtom()tryPunctuation()

func (p *Parser) parseAdd() (interface{}, error)

您正在阅读免费版教程,从第4章起只有简单的指引,适合爱好挑战和自学的读者。
可以购买有详细指导+背景知识的完整版