淘宝数据库OceanBaseSQL编译器部分源码阅读--解析SQL语法树(六)

2014-11-24 17:02:50 · 作者: · 浏览: 6
.3中截取的Select语法:

SelectStmt: select_no_parens      %prec UMINUS
      | select_with_parens    %prec UMINUS
    ;

select_with_parens:
      '(' select_no_parens ')'       
      | '(' select_with_parens ')'   
    ;
select_no_parens:
      simple_select           
      | select_clause sort_clause
      | select_clause opt_sort_clause for_locking_clause opt_select_limit
      | select_clause opt_sort_clause select_limit opt_for_locking_clause
      | with_clause select_clause
      | with_clause select_clause sort_clause
      | with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit
      | with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause
    ;

select_clause:
      simple_select             
      | select_with_parens      
    ;
simple_select:
      SELECT opt_distinct target_list
      into_clause from_clause where_clause
      group_clause having_clause window_clause
      | values_clause             
      | TABLE relation_expr
      | select_clause UNION opt_all select_clause
      | select_clause INTERSECT opt_all select_clause
      | select_clause EXCEPT opt_all select_clause
    ;

不知道你是不是有种似曾相识的感觉。没错,在这里,OceanBase借鉴了PostgreSQL的语法分析方式。PostgreSQL号称世界上最优秀的开源数据库,绝非浪得虚名。

update语法

为保证示例的完整性,我们在来分析下update的语法。

/*0.3版本的OceanBase*/
update_stmt: 
    UPDATE relation_factor SET update_asgn_list opt_where
  ;

update_asgn_list: 
    update_asgn_factor
  | update_asgn_list ',' update_asgn_factor
  ;

update_asgn_factor:
    NAME COMP_EQ expr
  ;

上面为0.3版本中的update的语法,支持常见的update的SQL语句,如果将它和0.4版本的update的语法相比,就会发现:0.4版本的update在set时可以使用保留关键字作为列名,支持hint语法,支持when子句。随着OceanBase逐渐完善,其解析的语法也必然会越来越复杂。在学习的时候,从一个简单的版本开始,由易到难,就显得很重要。

/*0.4版本的OceanBase*/
update_stmt:
    UPDATE opt_hint relation_factor SET update_asgn_list opt_where opt_when
  ;
update_asgn_factor:
    column_name COMP_EQ expr
  ;
column_name:
    NAME
  | unreserved_keyword
  ;
opt_when:
    /* EMPTY */
  | WHEN expr
  ;

除了select,比较复杂还有create table,alter table,expr等。本节最后只讨论表达式的语法问题。其他的不再讨论。

表达式语法

expression 是指表达列名或者是一个能够给出真假的布尔表达式。如

a+3 > b

a is not null

等等。表达式最常出现在where子句中,用于过滤数据行。

表达式的语法之所以复杂,是因为表达式可以嵌套多个子表达式,多个子表达式出现后可能会出现语法上的歧义。BETWEEN ... AND 用于测试给的表达式是否在给定的范围内,这个操作符中的AND 与逻辑与的AND有歧义。需要使用%prec来改变其优先级和结合性,该方法能奏效,但是PostgreSQL和OceanBase都选择从语法树规则上完全消除该歧义。

OceanBase中表达式有3种类型,分别为expr , arith_expr , simple_expr。其中

expr :expr为表达式的核心,是不受约束的表达式,可以直接用于where,having等子句中。
arith_expr :arith_expr是可以用于between ... and之间的表达式,是受约束的表达式。因此arith_expr是expr的一个真子集。
simple_expr :simple_expr是简单表达式,不能直接进行自我递归的表达式。是expr和aritharith_expr的共有的部分。
expr_const:
    STRING 
  | DATE_VALUE 
  | INTNUM 
  | APPROXNUM 
  | BOOL 
  | NULLX 
  | QUESTIONMARK 
  | TEMP_VARIABLE 
  | SYSTEM_VARIABLE 
  | SESSION_ALIAS '.' column_name 
  ;

simple_expr:
    column_ref
  | expr_const
  | '(' expr ')'
  | '(' expr_list ',' expr ')'
  | case_expr
  | func_expr
  | when_func
  | select_with_parens        %prec UMINUS
  | EXISTS select_with_parens
  ;

/* used by the expression that use range value, e.g. between and */
arith_expr:
    simple_expr   
  | '+' arith_expr %prec UMINUS
  | '-' arith_expr %prec UMINUS
  | arith_expr '+' arith_expr 
  | arith_expr '-' arith_expr 
  | arith_expr '*' arith_expr 
  | arith_expr '/' arith_expr 
  | arith_expr '%' arith_expr 
  | arith_expr '^' arith_expr 
  | arith_expr MOD arith_expr 

expr:
    simple_expr   
  | '+' expr %prec UMINUS
  | '-' expr %prec UMINUS
  | expr '+