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

2014-11-24 16:57:27 · 作者: · 浏览: 3
Node* table_node = node->children_[0]; //解析表 ret = resolve_table(result_plan, update_stmt, table_node, table_id); update_stmt->set_update_table(table_id); ParseNode* assign_list = node->children_[1]; uint64_t ref_id; ColumnItem *column_item = NULL; //解析要更新的列表,如:update student set sex="M",grade="2" where name = "xiaoming"; for (int32_t i = 0; ret == OB_SUCCESS && i < assign_list->num_child_; i++) { ParseNode* assgin_node = assign_list->children_[i]; /* resolve target column */ ParseNode* column_node = assgin_node->children_[0]; ObString column_name; column_name.assign_ptr( (char*)(column_node->str_value_), static_cast(strlen(column_node->str_value_)) ); //1 根据列名获取列 column_item = update_stmt->get_column_item(NULL, column_name); //2 解析列到vector ret = update_stmt->add_column_item(*result_plan, column_name, NULL, &column_item); //3 增加列引用到update_stmt ret = update_stmt->add_update_column(column_item->column_id_); /* resolve new value expression */ //4 解析值表达式 ParseNode* expr = assgin_node->children_[1]; ret = resolve_independ_expr(result_plan, update_stmt, expr, ref_id, T_UPDATE_LIMIT); //5 添加值表达式引用到update_stmt ret = update_stmt->add_update_expr(ref_id) } //解析where子句 ret = resolve_where_clause(result_plan, update_stmt, node->children_[2]); return ret; }

我们仍旧以update语句为例。上面是根据源代码整理的逻辑,不是源码,主要是为了理清思路。

  1. 首先是创建一个新的查询update_stmt,并为其生成一个独立的查询标识qid
  2. 解析语句中的表,并将表的标识tid添加到update_stmt的引用列表
  3. 利用for循环逐个解析要更新的列-值对:
    (1). 根据列名获取列;
    (2). 将该列存储到update_stmt的vector中,并将列引用id添加到update_stmt的更新列列表ObArray update_columns_中;
    (3). 解析值表达式;
    (4). 将值表达式引用id添加到更新值列表ObArray update_exprs_中去;
  4. 解析where子句.

    3.2 如何解析表和列?

    通过上面我们知道,逻辑计划的解析的一个重要内容就是要确定查询stmt,表,列,表达式的标识.查询和表达式的标识id都可以在解析的时候生成。因为这两项不是线程共有的,但是表和列是持久的数据,可以跨线程使用同样的id。这些表和列的信息由谁来管理?

    3.2.1 使用Schema

    追根溯源,你会发现实体表和列的id是在ob_schema.cpp中获取的。什么是schema?schema就是数据库对象的一个集合。网上有一个很形象的比喻,我稍微做了点改动:

    什么是Database,什么是Schema,什么是Table,什么是列,什么是行,什么是User?我们可以可以把Database看作是一个大仓库,仓库分了很多很多的房间,Schema就是其中的房间,一个Schema代表一个房间,Table可以看作是每个Schema中的柜子,行和列就是柜子中的格子。User就是房间的主人。

    OceanBase要求schema强类型约束,也就是要预先定义好schema。这样可以方便的进行各种online ddl操作。

    OceanBase的表和列信息存储在Schema的一个hash_map中。关于Schema 以后再深入了解。

    四、总结

    制定逻辑计划,最关键的是要理解逻辑计划的设计目标,其中最主要的内容就是确定逻辑计划中使用到的查询Stmt,表,列,表达式,并为它们生成或设置唯一标识,确保在同一个逻辑计划中是不相同的。制定逻辑计划的函数只要是reslove系列函数。而表和列的信息存储在Schema中一个hash_map中。


    欢迎光临我的网站----我的博客园----我的CSDN。
    如果阅读本文过程中有任何问题,请联系作者,转载请注明出处!