DSL规则语法组件介绍
DSL规则引擎定义了一套语言语法规范,DSL语法可以描述为:"原模板 "=>"目标模板"的形式,用于将QueryTree与原模板匹配的节点 ,改写成根据目标模板构建的节点。其中模板由:语法关键词 、符号、变量 、函数和约束组成,其组成方式如图1所示。
| 语法组件名称 | 语法组件介绍 | 约束 |
|---|---|---|
| 语法关键词 |
|
|
| 符号 |
| - |
| 变量 | DSL提供'$' + var_string的形式表达变量。变量用于在和QueryTree中的表达式进行匹配时,在表达式匹配成功后将变量和表达式形成映射关系,便于后续处理。以JOIN关键词为例: JOIN<INNER>{
LEFT: $l_var: *
RIGHT: $r_val: *
ON: $cond: *
} 其中LEFT: $l_var: *表示匹配的是JOIN的左子树,变量为$l_var,匹配的是左子树所有表达式,则左子树表达式和$l_var形成映射关系,即$l_var表示左子树的表达式,同理$r_val表示匹配右子树的所有表达式,$cond表示匹配JOIN所有的连接条件。 | - |
| 函数 |
| |
| 约束 | 表示约束检查,当有多个约束条件时,约束函数通过'&&'进行拼接,如图2所示。满足所有约束时表示条件满足,匹配成功。每一个算子都可以有自己的约束。约束一般由约束函数构成,约束函数请参见表5。 | - |
| 关键字名称 | 模板语法 | 支持类型 | 解释 |
|---|---|---|---|
| QUERY | QUERY<QUERY_TYPE> {
PREPROCESS: ($PREPROCESS)
CTE: ($cte_expr: *)
PROJECT: ($proj_expr: *)
FROM: ($from_expr: *)
FILTER: ($filter_expr: *)
GROUP: GROUP<> {$group_expr: *}
SORT: ($sort_expr: *)
LIMIT: LIMIT<> {$limit_expr: *}
POSTPROCESS: ($POSTPROCESS)
MAINBLOCK: false
} | 该关键字用于匹配一个完整的QUERY或SUBQUERY结构,其中固有参数如下(以下参数的顺序固定,需要注意的是,所有参数均支持省略,表示不匹配对应参数或执行对应操作):
| |
| JOIN | JOIN<JOIN_TYPE> {
ALIAS: ($alia: *)
LEFT: ($left_expr: *)
RIGHT: ($right_expr: *)
ON: ($on_expr: *)
ONLY_TOP: false
RECURSE_MODE($MODE)
} | 该关键字用于匹配JOIN连接的内容,其中固有参数如下:
| |
| GROUP | GROUP<> {
GROUP: ($group_expr: *)
FILTER: ($filter_expr: *)
GROUPSET: ($groupset_expr: *)
} | 无类型信息。 | 该关键字用于匹配一个GROUP BY结构,其中固有参数如下:
|
| LIMIT | LIMIT<> {
LIMIT: ($limit_expr: *)
OFFSET: ($offset_expr: *)
} | 无类型信息。 | 该关键字用于匹配一个LIMIT结构,其中固有参数如下:
|
| AGG | AGG<AGG_TYPE> {
ARGS: ($exprs: *)
DISTINCT: *
} | 该关键字支持匹配所有AGG函数,并且可以指定type类型匹配具体的AGG函数,如:AGG<>表示匹配所有AGG函数;AGG<MIN|MAX>表示匹配min和max类型的AGG函数,其中固有参数如下:
说明: AGG关键字匹配支持省略ARGS参数,当该参数省略时,其他参数也必须省略,如下两个场景所示:
| |
| SUBLINK | SUBLINK<SUBLINK_TYPE> {
TEST_EXPR: ($test: *)
QUERY: ($exprs: *)
} | 该关键字用于匹配一个SUBLINK结构,其中固有参数如下:
| |
| CROSS | CROSS<> {
ARGS: ($exprs: *)
} | 无类型信息。 | 该关键字用于匹配一个笛卡尔积,其中固有参数如下: ARGS:笛卡尔积的表信息。 |
| SET | SET<SET_TYPE> {
LEFT: ($left_expr: *)
RIGHT: ($right_expr: *)
MATCHTYPE_ALLSAME: *
IGNOREUNMATCHTYPE: *
} | 该关键字用于匹配一个集合,其中固有参数如下:
说明: SET关键字匹配支持使用通用模板匹配模式,该模式下可以省略RIGHT关键字及其表达式信息。当存在多个子查询时,该模式可一次性匹配所有满足LEFT关键字中表达式的节点,现固定写法如下(MATCHTYPE_ALLSAME采用默认值TRUE,IGNOREUNMATCHTYPE采用默认值FALSE): SET<xxx>
{
LEFT: $set_left : QUERY<xxx> {xxx}
} 后续可以与FOREACH_NODES_WITH_TEMPLATE函数结合使用,使用方法如下: FOREACH_NODES_WITH_TEMPLATE $set_left (xxx_func) | |
| PROJECT | PROJECT<> {
ARGS: ($exprs: *)
MATCHALL: *
} | 无类型信息。 | 该关键字用于匹配投影列信息,其中固有参数如下:
说明: PROJECT关键字的固定用法如下,其返回值为批量匹配的投影列信息,MATCHALL省略使用默认值TRUE: $proj:PROJECT<>
{
ARGS: $exprs: *
} 后续可以与FOREACH_NODES_WITH_TEMPLATE函数结合使用,使用方法如下: FOREACH_NODES_WITH_TEMPLATE $proj (xxx_func) |
| CTE | CTE<$name:*> {
QUERY: $CTE_QUERY
} | 无类型信息。 | 该关键字用于匹配CTE结构,固有参数如下:
|
| 关键字名称 | 模板语法 | 支持类型 | 解释 |
|---|---|---|---|
| OR | OR<> {
ARGS: ($exprs: *)
} | 无类型信息。 | 该关键字用于匹配一个OR表达式结构,其中固有参数如下: ARGS:OR表达式的内容。 |
| AND | AND<> {
ARGS: ($exprs: *)
} | 无类型信息。 | 该关键字用于匹配一个AND表达式结构,其中固有参数如下: ARGS: AND表达式的内容。 |
| NOT | NOT<> {
ARGS: ($exprs: *)
} | 无类型信息。 | 该关键字用于匹配一个NOT表达式结构,其中固有参数如下: ARGS:NOT表达式的内容。 |
| BOOLEAN | BOOLEAN<BOOLEAN_TYPE> {
ARGS: ($exprs: *)
IGNORENULL: *
AUTOMATCH: *
} | 该关键字用于匹配一个BOOL类型表达式结构,其中固有参数如下:
| |
| CONST | CONST<CONST_TYPE> {
ARGS: ($exprs: *)
} | 该关键字用于匹配CONST表达式内容,其中固有参数如下: ARGS:CONST表达式的内容,可为空。 | |
| NULLTEST | NULLTEST<NULLTEST_TYPE> {
ARGS: ($exprs: *)
} | 该关键字用于匹配一个ISNULL或NOTNULL表达式,其中固有参数如下: ARGS:NULLTEST表达式的内容。 | |
| OPERATOR | OPERATOR<OPERATOR_TYPE>{
LEFT: ($left_expr: *)
RIGHT: ($right_expr: *)
IGNORESIDE: true
} | 该关键字用于匹配一个OPERATOR表达式,其中固有参数如下:
| |
| CASE | CASE<>{
ARGS: ($expr: *)
DEFRESULT: ($def: *)
} | 无类型信息。 | 该关键字用于匹配一个CASE表达式,其中固有参数如下:
|
| WHEN | WHEN<>{
ARGS: ($expr: *)
DEFRESULT: ($def: *)
} | 无类型信息。 | 该关键字用于匹配一个WHEN表达式,其中固有参数如下:
|
| COL | COL<> {
ARGS: ($exprs: *)
} | 无类型信息。 | 该关键字用于匹配一个表的属性列表达式,其中固有参数如下: ARGS:COL表达式的内容。 |
| 关键字名称 | 模板语法 | 解释 |
|---|---|---|
| CONSTRAINTS | CONSTRAINTS:/* CONTENT */ | 该关键字用于约束结构关键字或表达式扩展关键字,可以作为表2及表3包含关键字的最后一个入参使用。示例如下: /* 约束QUERY关键字包含LIMIT子句 */
QUERY<> {
PROJECT: $proj:*
FILTER: $sub_filter:*
CONSTRAINTS: (check_has_constraint THIS LIMIT)
} |
| TEMPLATE | TEMPLATE { /* CONTENT */ } | 该关键字用于约束函数或表达式计算函数的入参,其内容不可以为空,内容可以为结构关键字或表达式扩展关键字,当函数实现需要使用模板而非其构造成的表达式时,可以使用该关键字,各函数支持的关键字参见各函数说明。示例如下: /* find_nodes_with_template使用模板template {DSLSTRUCT}匹配$redundant_info中的相关内容,并将结果映射到$r_info_template,供后续使用,如果DSLSTRUCT不使用TEMPLATE关键字,则会被解析为一个表达式而不是模板 */
$r_info_template: (find_nodes_with_template $redundant_info template {DSLSTRUCT}) |
| THIS | THIS | 该关键字用于约束函数或表达式计算函数的入参,指代当前所属范围的QUERY BLOCK。示例如下: /* 删除THIS指代的当前QUERY BLOCK无用的表信息 */ POSTPROCESS: (remove_unused_table THIS) |
| ROOT | ROOT | 该关键字用于约束函数或表达式计算函数的入参,指代第一层的QUERY BLOCK。示例如下: /* 约束ROOT指代第一层QUERY BLOCK包含LIMIT子句 */ CONSTRAINTS: (check_has_constraint ROOT LIMIT) |
| 函数名 | 函数原型 | 参数说明 | 功能描述 |
|---|---|---|---|
| EXPR_COMPUTE | Node expr_compute(Node $args) | 常量表达式计算,例如将提取的表达式中可以计算为常量的表达式进行预处理,方便后续逻辑分析。 例如,将表达式中的1+1进行提前计算,得到常量值2;或者将1= 0进行提前计算,得到常量值false。 | |
| BUILD_PROJECT | Node build_project(Node $args) | 通过传入的表属性列,构造对应的投影列集合。 | |
| BUILD_TABLE | Node build_table(Node $args) | 根据入参构造新的表。 | |
| BUILD_BOOL_EXPR | Node build_bool_expr(DSLType $bool_type, Node $args1, DSLNode $args2) |
| 构造指定类型的布尔表达式。 |
| BUILD_GROUP | Node build_group(Node $args) | 根据输入表属性列构造分组信息。 | |
| BUILD_FROMEXPR_BY_QUERY | Node build_fromexpr_by_query(Query $query, Node $table) | 根据传入的表创建Query结构体的From表达式。 | |
| REMOVE_DISTINCT | bool remove_distinct(DSLExpr $query) | 删除目标QUERY的DISTINCT部分。 | |
| REMOVE_UNUSED_TABLE | bool remove_unused_table(DSLExpr $query) | 删除目标QUERY的无用表,当对QUERY的FROM部分进行修改或重新创建时,需要执行该函数。 | |
| FIND_UNIQUE_ATTR | List find_unique_attr(List $args, UniqueType $type) | 检查表基表是否包含唯一键。 | |
| FIND_TABLES | List find_tables(DSLNode $args, TableType $type, DSLType $include_join) |
| 从节点中提取所有的Table表。 |
| FIND_ATTRIBUTES | List find_attributes(DSLNode $tablelist, DSLNode $args) List find_attributes(DSLNode $tablelist, DSLNode $args, DSLNode $table_query, DSLNode $find_attri_marks, DSLNode $do_dedup) |
| 从节点中提取相关表属性。 |
| APPEND | List append(List $arg1, List $arg2) | 在一个List中追加另一个节点或List,或者将两个节点构造成一个List。 | |
| REPLACE_WITH | Node replace_with(DSLNode $arg1, DSLNode $arg2, DSLNode $arg3) bool replace_with(DSLNode $arg1, DSLNode $arg2, DSLNode $arg3, DSLNode $replace_node_option) bool replace_with(DSLNode $arg1, DSLNode $arg2, DSLNode $arg3, DSLNode $replace_node_option, DSLNode $replace_node_mode) |
| 用$arg3节点替换$arg1父节点中的$arg2节点。 |
| REPLACE_WITH_REC | Node replace_with_rec (DSLNode $arg1, DSLNode $arg2, DSLNode $arg3) bool replace_with_rec (DSLNode $arg1, DSLNode $arg2, DSLNode $arg3, DSLNode $replace_node_option) |
| 用$arg3节点替换父节点中递归查找到的$arg1节点。 |
| REPLACE_TABLE | Node replace_table (QUERY $arg1, DSLNode $arg2, DSLNode $arg3, DSLNode $arg4 = DIRECT) |
| 使用$arg4标识的方式,用$arg3表节点替换$arg1QUERY节点中的$arg2表节点。 |
| REPLACE_TABLE_FOREACH | Node replace_table (QUERY $arg1, DSLNode $arg2, DSLNode $arg3) | 用$arg3表节点替换QUERY节点中的$arg2集合中所有表节点。 | |
| FIND_EXPR_WITHOUT | List find_expr_without(Expr $args1, Expr $args2) | 从$args1父表达式节点中查找不包含指定$args2表达式节点的部分。 | |
| FIND_EXPR_WITH | List find_expr_with(Expr $args, DSLType $flags, DSLType $any_all_type) | 从$args表达式中查找包含指定条件的部分。 | |
| LIST_FIRST | Node list_first(List $args) | 提取$args列表的第一个节点。 | |
| LIST_LENGTH | Integer list_length(List $args) | 获取列表的长度。 | |
| PULL_RELA_ATTR | List pull_rela_attr(Expr $args, DSLType $flags) | 提取表达式中满足层数条件的表达式节点。 | |
| PULL_EXPR_TO_QUERY | Node pull_expr_to_query(List $args, Query $query) | 将$arg表属性节点提取到$query的节点中。 | |
| BUILD_EXPR_THROUGH_PULLUP | Node build_expr_through_pullup(Node $args, Query $query) | 通过相关的表达式和新创建的表,构建新的表达式。其中表达式中的表属性与新的表属性映射。 | |
| REMOVE_QUERY_OPTION | bool remove_query_option(Query $query, DSLType $remove_query_options) | 移除Query结构体中的指定部分。 | |
| BUILD_WHEN_EXPR | CaseWhen build_when_expr(CaseWhen $casewhen) | 生成CaseWhen结构体。 | |
| BUILD_CASE_EXPR | CaseExpr build_case_expr(CaseExpr $caseexpr) | 生成CaseExpr结构体。 | |
| FIND_SAME_TABLES | List find_same_tables(List $args, DSLType $type) | 查找相同的表,默认不支持指定分区场景。 说明: 指定分区场景示例: SELECT * FROM t1 partition(p1), t2 partition(p2) WHERE t1.c1=t2.c1; 该示例中,使用partition关键字指定了特定的分区。 | |
| FIND_NODES_WITH_TEMPLATE | List find_nodes_with_template(Node $node, DSLNode $template, DSLType $rec_mode) |
| 遍历结构体,查找与目标模板相匹配的结构。 |
| FOREACH_NODES_WITH_TEMPLATE | bool foreach_nodes_with_template(DSLNode $arg1, DSLNode $arg2) | 遍历链表中的每一个元素,并以指定的方式对每一个元素进行处理。 | |
| BUILD_SUBLINK | Sublink build_sublink(Node $sublink) Sublink build_sublink(Node $sublink, List $columns, List $operator) | 构建Sublink结构体。
| |
| DSLNODE_COPY | Node dslnode_copy(Node $node, DSLType $copy_node_option) | 复制DSLNode结构体。 | |
| FIND_EQUALCLASS_VARS | List find_equalclass_vars(BoolExpr $exprs, DSLNode $bool_expr_type, DSLNode $operator_type) | 根据表达式生成等价类。 | |
| FIND_REDUNDANT_INFO | List find_redundant_info(List $equalclass_list) | 根据等价类信息生成冗余信息,用于在某些优化规则中消除冗余表。 | |
| REMOVE_USELESS_CONDITION | BoolExpr remove_useless_condition(Query $query, BoolExpr $expr, DSLType $scenario_option, List $vars) |
| 删除冗余的谓词条件。 |

