淘宝数据库OceanBaseSQL编译器部分源码阅读--生成逻辑计划(二)

2014-11-24 16:57:27 · 作者: · 浏览: 1
RawExpr { };

在ObLogicalPlan中,存储使用的是vector,使用时转为vector.

2.4 逻辑计划中的Stmt的定义

Stmt表示一个单独的查询所包含的内容,一个逻辑计划可以包含多个Stmt.

   class ObStmt
    {
    /*省略部分内容...*/
    protected:
      common::ObVector    table_items_;
      common::ObVector   column_items_;

    private:
      StmtType  type_;
      uint64_t  query_id_;
      //uint64_t  where_expr_id_;
      common::ObVector     where_expr_ids_;

    };

Stmt包括了一个查询所有的表table_items_,列column_items_,表达式where_expr_ids_和一个唯一的查询标识query_id_。注意这里存储的只有表达式的id,而不是表达式的实际内容。

从上述的定义总结来看,一个逻辑计划拥有多条查询实例Stmt和多个表达式,一个查询实例Stmt包含了多个表和多个列及所需表达式的引用。表,列,表达式,查询实例都有唯一的标识符进行标记。

ObLogicalPlan
----ObStmt : 1...n
--------TableItem : 0...n
--------ColnumItem : 0...n
--------expr_id_ref : 0...n
----ObRawExpr : 0...n

三、 如何制定逻辑计划?

3.1 reslove系列解析函数

制定逻辑计划的源码在build_plan.h和build_plan.cpp中,在OceanBase0.4中,则增加了dml_build_plan.h和dml_build_plan.cpp。制定逻辑对外提供的接口只有两个,解析函数resolove和销毁函数destroy_plan,其他的为自用,可以浏览下其函数声明及用途,基本的结构就是这样,因为目前OceanBase中支持的SQL语句不多,相应的解析函数也比较少,还有一些没有完成,可以想见未来还会添加更多的函数。

//解析多重查询
int resolve_multi_stmt(ResultPlan* result_plan, ParseNode* node)
//解析独立表达式
int resolve_independ_expr()
//解析and表达式
int resolve_and_exprs()
//解析表达式
int resolve_expr()
//解析聚集函数
int resolve_agg_func()
//解析join表连接
int resolve_joined_table()
//解析表
int resolve_table()
//解析from子句
int resolve_from_clause()
//解析列
int resolve_table_columns()
//解析*
int resolve_star()
//解析select的投影列表
int resolve_select_clause()
//解析where子句
int resolve_where_clause()
//解析group by子句
int resolve_group_clause()
//解析having子句
int resolve_having_clause()
//解析order子句
int resolve_order_clause()
//解析limit子句
int resolve_limit_clause()
//解析select查询
int resolve_select_stmt()
//解析delete查询
int resolve_delete_stmt()
//解析insert的插入列
int resolve_insert_columns()
//解析intsert查询的插入值
int resolve_insert_values()
//解析insert查询
int resolve_insert_stmt()
//解析update查询
int resolve_update_stmt()
//解析函数。对外提供
int resolve(ResultPlan* result_plan, ParseNode* node)
//销毁函数,对外提供
extern void destroy_plan(ResultPlan* result_plan)

resolve函数根据语法树node的类型调用不同的查询解析实例。以下是部分代码摘抄:

int resolve(ResultPlan* result_plan, ParseNode* node)
{
   /*...*/

  uint64_t query_id = OB_INVALID_ID;
  if (ret == OB_SUCCESS && node != NULL)
  {
    switch (node->type_)
    {
      case T_STMT_LIST:
      {
        ret = resolve_multi_stmt(result_plan, node);
        break;
      }
      case T_SELECT:
      {
        ret = resolve_select_stmt(result_plan, node, query_id);
        break;
      }
      case T_DELETE:
      {
        ret = resolve_delete_stmt(result_plan, node, query_id);
        break;
      }
      case T_INSERT:
      {
        ret = resolve_insert_stmt(result_plan, node, query_id);
        break;
      }
      case T_UPDATE:
      {
        ret = resolve_update_stmt(result_plan, node, query_id);
        break;
      }
      default:
        ret = OB_ERROR;
        break;
    };
  }
  return ret;
}
int resolve_update_stmt(ResultPlan* result_plan, ParseNode* node, uint64_t& query_id)
{
  int& ret = result_plan->err_stat_.err_code_ = OB_SUCCESS;
  uint64_t table_id = OB_INVALID_ID;

  query_id = OB_INVALID_ID;

  ObLogicalPlan* logical_plan  logical_plan = new(logical_plan) ObLogicalPlan(name_pool);

  result_plan->plan_tree_ = logical_plan;


  update_stmt = new(update_stmt) ObUpdateStmt(name_pool);

  query_id = logical_plan->generate_query_id();
  //为update_stmt设置新的标识qid
  update_stmt->set_query_id(query_id);

  logical_plan->add_query(update_stmt);

  Parse