⚠
The web version only has simple instructions since chapter 04, while the full book has detailed explanations and background info.
0506: WHERE Expression
Parse WHERE
This step adds no new features. It refactor the WHERE part into an expression.
type StmtSelect struct {
table string
cols []interface{} // ExprUnOp | ExprBinOp | string | *Cell
// keys []NamedCell
cond interface{}
}
type StmtUpdate struct {
table string
// keys []NamedCell
cond interface{}
value []ExprAssign
}
type StmtDelete struct {
table string
// keys []NamedCell
cond interface{}
}Update parser:
func (p *Parser) parseSelect(out *StmtSelect) (err error) {
// ...
out.cond, err = p.parseWhere()
return err
}
func (p *Parser) parseWhere() (expr interface{}, err error)Match Expressions
During execution, extract primary key values from the expression:
func (db *DB) execSelect(stmt *StmtSelect) ([]Row, error) {
// ...
row, err := matchPKey(&schema, stmt.cond)
if err != nil {
return nil, err
}
if ok, err = db.Select(&schema, row); err != nil {
return nil, err
}
// ...
}
func matchPKey(schema *Schema, cond interface{}) (Row, error) {
if keys, ok := matchAllEq(cond, nil); ok {
return makePKey(schema, keys)
}
return nil, errors.New("unimplemented WHERE")
}matchAllEq() detects expressions like a = 123 AND b = 456 AND ... and outputs column names and values. It recursively walks the expression. Implement this:
func matchAllEq(cond interface{}, out []NamedCell) ([]NamedCell, bool)For now, only primary key queries that return a single row are supported. To add other query types, you must recognize other expression forms, such as range queries in the next step.
ⓘ
CodeCrafters.io has similar courses in many programming languages, including build your own Redis, SQLite, Docker, etc. It’s worth checking out.