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 '+