CryptDB代码分析2-handler与executor

之前已经介绍了SQL语句经过mysql-proxy的lua脚本与C++库交互的过程。在CryptDB的处理中,总体分为两个阶段:rewrite与next。本文介绍在rewrite和next这两个阶段中比较重要的两个类层次:handler以及executor。

SQL改写方式与query恢复介绍

首先考虑如何对SQL语句进行加密。CryptDB不直接处理字符串,而是借用了MySQL5.5版本的parser先对原始SQL语句进行解析,解析完以后获得一个LEX类型结构,是一个MySQL定义的类。 在加密阶段,对LEX内部的各个成员进行加密,并获得一个加密的LEX结构。 在恢复阶段,则需要将这个加密的LEX结构恢复成字符串类型,从而获得加密的SQL语句。

举例来说,对于一个SQL语句SELECT id from student, id 需要被加密。而这个语句解析成LEX 结构以后,id是在item_list成员里面,具体如下:


lex->select_lex.item_list

对这个item_list遍历,可以得到每个被选择的列对应的结构,是一个Item_field类型。其内部就包含了filed的名字,也就是id。加密过程,就是把这个内部的成员修改成自己想要的加密列的名字。完成LEX结构的加密以后,需要从LEX结构恢复成string类型的SQL语句,相关代码位于parser/stringify.hh。比如针对上面的SELECT语句,已经得到了加密以后的LEX结构,要重新得到字符串类型的SQL语句,可以通过如下的代码进行处理:

//代码来源 parser/stringfy.hh
//参数lex是加密以后的lex
static inline std::ostream&
operator<<(std::ostream &out, LEX &lex){
    String s;
    switch (lex.sql_command) {
    //对于select语句,直接调用一次函数就可以恢复SQL语句
    case SQLCOM_SELECT:
        //string类型的结果保存在ostream类型的变量out里面
        out << lex.unit;
        break;
    }
    ....
}

//该函数完成lex.unit到字符串的转化。
static inline std::ostream&
operator<<(std::ostream &out, SELECT_LEX_UNIT &select_lex_unit){
    String s;
    select_lex_unit.print(&s, QT_ORDINARY);
    return out << s;
}

所以, 加密过程其实就是SQL语句的解析,以及解析以后的类的成员的修改。要理解完整的SQL解析,加密,以及LEX结构恢复成字符串的代码流程,就需要了解MySQL的parser的内部类的含义,这些在后续的文章中会逐步介绍。

SQL解析与分类处理

在mysqlproxy/ConnectWrapper.cc的rewrite函数中完成了基本的SQL加密操作。其内部执行SQL加密的入口是:Rewriter::rewrite函数。该函数的作用是获得一个QueryRewrite类,这个类包含了改写以后的SQL语句,以及数据解密所需要的元信息。其部分代码如下:

QueryRewrite
Rewriter::rewrite(const std::string &q, const SchemaInfo &schema,
                  const std::string &default_db, const ProxyState &ps) {
     //辅助信息
    Analysis analysis(default_db, schema, ps.getMasterKey(),
                      ps.defaultSecurityRating());
    //SQL解析,加密,获得executor类型,在next阶段使用
    AbstractQueryExecutor *const executor =
        Rewriter::dispatchOnLex(analysis, q);
    if (!executor) {
        return QueryRewrite(true, analysis.rmeta, analysis.kill_zone,
                            new NoOpExecutor());
    }
    //QueryRewrite类包含所有必要信息
    return QueryRewrite(true, analysis.rmeta, analysis.kill_zone, executor);
}

首先是调用Rewriter::dispatchOnLex函数, 获得executor, 然后返回QueryRewrite类。其中executor中就保存了加密以后的SQL语句。在dispatchOnLex函数中,首先调用MySQL的parer对原始的SQL语句进行解析,获得LEX结构, 然后根据lex.sql_command把SQL语句分为三类:noRewrite,ddl以及dml。不同类型的sql语句分配不同的handler类型进行处理,并返回executor类型,具体如下:

  • 对于noRewrite类型, 直接返回SimpleExecutor类型,其作用是直接返回明文的SQL语句,不进行任何的SQL改写操作。
  • 对于DML以及DDL,则分别由不同的handler类型对SQL语句进行处理,并且返回对应的executor结构。

其简化的代码如下:

AbstractQueryExecutor *
Rewriter::dispatchOnLex(Analysis &a, const std::string &query) {
    //使用MySQL的parser进行SQL解析,获得LEX类型
    LEX *const lex = query_parse(query);
    //三种不同的处理
    if(noRewrite(*lex)){
        return new SimpleExecutor();
    }else if(dml_dispatcher
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值