再读simpledb 之 SQL语句解析(2)

(1)里面提到,lexer作为一个工具,完成了对SQL字符串的切割,将语句转化成一个tokens数组。

Parser完成了SQL解析的后序部分:使用一个lexer对象作为工具,切出tokens,然后解析语义,绑定相关的系统接口。

在这里先要回顾下simpledb的支持的SQL的语法,这个影响了它在解析字符串时使用的方法。

<Query>      := SELECT <SelectList> FROM <TableList> [ WHERE <Predicate> ]
<SelectList> := <Field> [ , <SelectList> ]
<TableList>  := TableName [ , <TableList> ]
<Predicate>  := <Term> [ AND <Predicate> ]
<Term>       := <Expression> = <Expression>
<Expression> := <Field> | <Constant>
<Field>      := FieldName
<Constant>   := String | Integer
 
<Modify>     := <Insert> | <Delete> | <Update> 
<Insert>     := INSERT INTO TableName ( <FieldList> ) VALUES ( <ConstList> )
<FieldList>  := <Field> [ , <FieldList> ]
<ConstList>  := <Constant> [ , <Constant> ]
<Delete>     := DELETE FROM TableName [ WHERE <Predicate> ]
<Update>     := UPDATE TableName SET <Field> = <Expression> [ WHERE <Predicate> ]
 
<Create>     := <CreateTable> | <CreateView> | <CreateIndex>
<CreateTable>:= CREATE TABLE TableName ( <FieldDefs> )
<FieldDefs>  := <FieldDef> [ , <FieldDefs> ]
<FieldDef>   := FieldName <TypeDef>
<TypeDef>    := INT | VARCHAR ( Integer )
<CreateView> := CREATE VIEW ViewName AS <Query>
<CreateIndex>:= CREATE INDEX IndexName ON TableName ( <Field> )

Parser这里实现的编译技术中的“一趟编译”,即通过lex顺序扫描tokens数组,在扫描过程中完成对各个token元素的识别,按照

constant/field –> Expression –> Term –> Predicate

的层递关系,完成参数包装,输出一个查询关联的数据类,如(1)中的类图1所示。

首先,以(1)图2的例子“select sid,sname from students where sid='10001' ”,给出一个parser解析过程中构建的语法树:

图1 示例语法树

以下是Query方法的代码:

public QueryData query()
{
    lex.eatKeyword("select");
    List<string> fields = selectList();
    lex.eatKeyword("from");
    List<string> tables = tableList();
    Predicate pred = new Predicate();
    if (lex.matchKeyword("where"))
    {
        lex.eatKeyword("where");
        pred = predicate();
    }
    return new QueryData(fields, tables, pred);
}

由代码和上面的语法树看出来,simpledb在解析SQL语句的时候,严格按照语法中支持的类型,“卡住”关键字,从中解析出字段列表fieldlist,表名列表tablelist,以及谓词列表predicates,然后将这些查询中实际用到的数据,包装成相应的对象,SQL语句的解析就初步完成。以上面的例子为例,QueryData对象包装完之后,会传递给查询处理模块,通过query下的一些方法,根据fieldlist,tablelist,和predicates来完成查询数据的读取。

parser中create(), delete(), insert(),query(), modify()方法,对应了上面的几类语法

作为SQL语句解析的入口,有如下的updateCMD方法,根据SQL语句首个token的不同,进行了分支:

public object updateCmd()
{
    if (lex.matchKeyword("insert")) 
        return insert();
    else if (lex.matchKeyword("delete"))
        return delete();
    else if (lex.matchKeyword("update"))
        return modify();
    else
        return create();
}

补充一点,注意下上面的query()的代码,lex用match*()来检测下一个token是否满足匹配条件,用eat*()来讲满足条件的token处理掉:

public void eatDelim(char d);
public string eatId();
public int eatIntConstant()
public void eatKeyword(string w)
public string eatStringConstant()

 数据相关的,均有返回值,返回处理后的结果;数据无关的,没有返回值,实际只是利用nextToken移动position指针。

关于tablelist、fieldlist的构建,使用了递归的方式实现:

private List<string> fieldList()
{
    List<string> l = new List<string>();
    l.Add(field());
    if (lex.matchDelim(','))
    {
        lex.eatDelim(',');
        l.AddRange(fieldList());
    }
    return l;
}

谓词 predicates也是用了递归的形式:

private Predicate predicate()
{
    Predicate pred = new Predicate(term());
    if (lex.matchKeyword("and"))
    {
        lex.eatKeyword("and");
        pred.conjoinWith(predicate());
    }
    return pred;
}

 略有不同的是,在谓词连接的时候,使用了Predicate类的conjoinwith方法,实际上,predicate对象下,维护了一个条件列表terms,这个方法就是把谓词中的各个term转存到一起。

 

本文和前一节只是扼要地描述了SQL语句解析的思路和过程,可以看到解析的结果就是生成了各种查询data,这些data会传递给query模块,由query模块利用这些得到的data,完成数据的查询。

转载于:https://www.cnblogs.com/YFYkuner/archive/2012/09/12/2682656.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值