
# DSL规则示例与说明
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
本章节内容为DSL规则匹配的示例与说明，执行结果不为实际执行结果。
#### 规则示例场景描述
- 简要描述：两个包含Count聚集函数的表达式子链接进行等值比较时，如果其中一个子链接可以表示为另一个子链接的子结构，且过滤条件仅相差一个EXISTS子链接条件时，可以对其进行优化。因为在此场景下，实际是想找到EXISTS条件返回FALSE的情况，在这种情况下两个count值是否相等取决于其他条件是否为TRUE。当其他条件为TRUE时，根据AND条件的语义，两个子链接的过滤条件相反，count()取值一定不同；否则取值相同。因此，对于这种场景可以使用NOT EXISTS等价改写消减子链接的数量。
- SQL示例：
  改写前：
  ```
  SELECT t1.a,
      t1.b
  FROM table1 as t1,
      table2 as t2
  WHERE t1.a = t2.a
      AND t1.b = t1.b
      AND (
          SELECT COUNT(*)
          FROM table1 as t11
          WHERE t11.a = t1.a
              AND t11.b = t1.b
      ) = (
          SELECT COUNT(*)
          FROM table1 as t21
          WHERE t21.a = t1.a
              AND t21.b = t1.b
              AND EXISTS(
                  SELECT 1
                  FROM t3
                  WHERE t1.a = t3.a
              )
      );
  ```
  改写后：
  ```
  SELECT t1.a,
      t1.b
  FROM table1 as t1,
      table2 as t2
  WHERE t1.a = t2.a
      AND t1.b = t1.b
      AND NOT EXISTS (
          SELECT 1
          FROM table1 as t11
          WHERE t11.a = t1.a
              AND t11.b = t1.b
              AND NOT EXISTS(
                  SELECT 1
                  FROM t3
                  WHERE t1.a = t3.a
              )
      );
  ```
  
 
#### 规则示例场景DSL规则
```
QUERY <> {
    FILTER: $exprs: * &&
                    (AND<>{
                        ARGS: $and_exp: * && ($eq_expr: OPERATOR<EQ>{
                            LEFT: SUBLINK<EXPRSUBLINK>{
                                QUERY: $ori_query: QUERY<>{
                                PROJECT: $proj1: AGG<COUNT>{ARGS: $agg_args1: *}
                                FROM: $input1: * && ($sub_l_t: (find_tables $input1 ALL))
                                FILTER: $FILTER1 : * && (AND<> {ARGS: $f_1 : * && (OPERATOR<EQ>{
                                    LEFT:$f_1_l : *
                                    RIGHT:$f_1_r : *
                                    CONSTRAINTS: ((check_has_constraint $f_1_l UPPERVAR) 
                                        && !(check_has_constraint $f_1_r UPPERVAR)) ||
                                        (!(check_has_constraint $f_1_l UPPERVAR) 
                                        && (check_has_constraint $f_1_r UPPERVAR)) &&
                                        !(check_has_constraint THIS MODIFYCTE | VOLATILE)
                                    })})
                                GROUP: GROUP<> {
                                    GROUP: $gr1: * && ($att_list: (find_attributes $gr1 THIS))
                                    FILTER: $h_c1: *
                                    GROUPSET: $gr_s1: *
                                    }
                                SORT: $s1 : *
                                        }
                                        }
                            RIGHT: SUBLINK<EXPRSUBLINK>{
                                QUERY: QUERY<>{
                                    PROJECT: $proj2 : AGG<COUNT>{ARGS: $agg_args2: *}
                                    FROM: $input2: * && ($sub_r_t: (find_tables $input2 ALL))
                                    FILTER: $FILTER2 : * && (AND<> {ARGS: $f_2 : *
                                            && ($orther_f: SUBLINK<existssublink>{QUERY: $ssub_query: *})})
                                        && ($same_set : (find_expr_without $f_2 $orther_f))
                                    GROUP: GROUP<> {
                                        GROUP: $gr2: *
                                        FILTER: $h_c2: *
                                        GROUPSET: $gr_s2: *
                                    }
                                    SORT: $s2 : *
                                    CONSTRAINTS: (check_is_equal $same_set $f_1) 
                                        && (check_is_equal $gr1 $gr2)
                                        && (check_is_equal $h_c1 $h_c2) && (check_is_equal $gr_s1 $gr_s2)
                                        && (check_is_equal $s1 $s2) 
                                        && (((check_type_foreach $proj1 COUNT_STAR) 
                                        && (check_type_foreach $proj2 COUNT_STAR)) ||
                                        ((check_type_foreach (expr_compute $agg_args1) CONST) 
                                        && (check_type_foreach (expr_compute $agg_args2) CONST)) ||
                                        ((check_type_foreach $agg_args1 COL) 
                                        && (check_type_foreach $agg_args2 COL) 
                                        && (check_is_equal $agg_args1 $agg_args2)))
                                        && !(check_has_constraint THIS MODIFYCTE | VOLATILE)
                                }
                            }
                            IGNORESIDE:true
                        })
                    }) && ($orther_expr: (find_expr_without $and_exp $eq_expr))
    CONSTRAINTS: (check_has_constraint ROOT SUBLINK) &&
                (check_type_foreach $exprs AND) 
                && (check_type_foreach $FILTER1 AND) && (check_type_foreach $FILTER2 AND) &&
                (check_is_same_table $sub_l_t $sub_r_t) 
                && !(check_has_constraint ROOT MODIFYCTE | VOLATILE)
}
=>
QUERY <> {
    FILTER: (append $orther_expr NOT<>{
            ARGS: SUBLINK<existsSUBLINK>{
                    QUERY: QUERY<SELECT>{
                        PROJECT: CONST<INTEGER>{ARGS:1}
                        FROM: (build_fromexpr_by_query $ori_query $input1)
                        FILTER: AND <> { ARGS : (append $same_set NOT<>{
                                ARGS: $orther_f
                            })
                        }
                        GROUP: GROUP<> {
                        GROUP: (build_group $att_list)
                        FILTER: $h_c1
                        GROUPSET: $gr_s1
                        }
                        SORT: $s1
                        }
                    }
                }
        )
}
```
#### 规则示例场景DSL规则详细解析
- 匹配部分：
  - QUERY\<\>：表示匹配的是默认类型的QUERY，即SELECT类型的QUERY。
  
  - FILTER\<\>：表示匹配的是约束条件。
  
  - ARGS: $exprs: \* ：表示约束条件的所有内容映射到变量exprs上；\&\&表示进一步匹配。
  
  - AND\<\> ：表示仅匹配AND条件。
  
  - ARGS: $and_exp: \*：表示将匹配的AND表达式的所有内容与变量and_expr做映射。ARGS: OPERATOR\<EQ\>：表示匹配等值表达式。
  
  - LEFT: SUBLINK\<EXPRSUBLINK\>、RIGHT: SUBLINK\<EXPRSUBLINK\>表示等值表达式的左右取值必须是子链接，且子链接中PROJECT: $proj1: AGG\<COUNT\>{}：表示投影列必须是COUNT()。
  
  - ((check_has_constraint $f_1_l UPPERVAR) \&\& !(check_has_constraint $f_1_r UPPERVAR)) \|\| (!(check_has_constraint $f_1_l UPPERVAR) \&\& (check_has_constraint $f_1_r UPPERVAR))：约束检查等值表达式一侧包含上层的VAR，即包含相关性条件。
    
  
  - GROUP，SORT：匹配子链接中的GROUP及SORT部分。
  
  - AND\<\> {ARGS: $f_2 : \* \&\& ($orther_f: SUBLINK\<EXISTSSUBLINK\>{QUERY: $ssub_query: \*})}：对于右SUBLINK在约束里的AND条件中存在一个EXISTSSUBLINK。
  
  - $same_set : (find_expr_without $f_2 $orther_f)：表示提取$f_2中排除$orther_f的部分，映射到变量$same_set上。
  
  - IGNORESIDE:true：表示左右两侧值可以互换进行模板匹配。
  
  - CONSTRAINTS: (check_is_equal $same_set $f_1)：表示两个子链接除右侧子链接的EXISTSSUBLINK外，其余部分都相同。
  
  - ($orther_expr: (find_expr_without $and_exp $eq_expr))： 同样表示从约束中提取非匹配的部分。
  
  - (((check_type_foreach $proj1 COUNT_STAR) \&\& (check_type_foreach $proj2 COUNT_STAR)) \|\| ((check_type_foreach (expr_compute $agg_args1) CONST) \&\& (check_type_foreach (expr_compute $agg_args2) CONST)) \|\| ((check_type_foreach $agg_args1 COL) \&\& (check_type_foreach $agg_args2 COL) \&\& (check_is_equal $agg_args1 $agg_args2)))：表示左右子链接的count()函数的参数只能为count(\*)、count(常量)或count相同的列。
   
- 改写部分：
  - QUERY\<\>和原模板一致。
  
  - Filter\<\>和原模板一致。
  
  - ARGS：表示成员变量；append是内部函数表达将两个表达式组成链表；append $orther_expr NOT\<\>表示$orther_expr所映射的表达式和NOT后续表示的表达式做组合。
  
  - ARGS: SUBLINK\<EXISTSSUBLINK\>： Not下是一个EXISTS子链接。
  
  - GROUP，SORT：构建子链接的GROUP或SORT部分。
  
  - QUERY: QUERY\<SELECT\> 表示子链接的QUERY成员为一个QUERY表达式。
  
  - PROJECT: CONST\<INTEGER\>{ARGS:1}：表示投影列为整数1。
  
  - FROM: (build_from_expr_from_query $ori_query $input1)：表示使用函数build_from_expr_from_query构造FROM部分。
  
  - FILTER: AND \<\> { ARGS : (append $same_set NOT\<\>：{ARGS: $orther_f}表示FILTER是AND表达式，表达式内容由append函数将$same_set所映射的表达式与$orther_f映射表达式构造NOT后进行组合。
   
 
#### 规则示例执行结果演示
```
EXPLAIN (costs off)SELECT t1.C, t1.b, t2.b FROM t1, t2 WHERE t1.a = t2.a AND (SELECT COUNT(*) FROM t1 as t11 WHERE t11.a = t1.a AND t11.b = t1.b) = (SELECT COUNT(*) FROM t1 AS t21 WHERE t21.a = t1.a AND t21.b = t1.b AND EXISTS(SELECT 1 FROM t3 WHERE t1.a = t3.a));
NOTICE:  Query with blockname(sel$1) is rewritten by Gs_Rewriter: SELECT t1.c, t1.b, t2.b FROM dsl_exprsublink_elimination.t1, dsl_exprsublink_elimination.t2 WHERE t1.a = t2.a AND NOT (EXISTS (SELECT 1::bigint FROM dsl_exprsublink_elimination.t1 t11 WHERE t11.a = t1.a AND t11.b = t1.b AND NOT (EXISTS (SELECT 1 AS "?column?" FROM dsl_exprsublink_elimination.t3 WHERE t1.a = t3.a)))); with rule_name sublink_compare_elimination
                                                   QUERY PLAN                                                   
----------------------------------------------------------------------------------------------------------------
 Hash Join
   Hash Cond: (t2.a = t1.a), (Expression Flatten Optimized)
   ->  Seq Scan on t2
   ->  Hash
         ->  Merge Anti Join
               Merge Cond: ((t1.a = t11.a) AND (t1.b = t11.b)), (Expression Flatten Optimized)
               Join Filter: (NOT (alternatives: SubPlan 1 or hashed SubPlan 2)), (Expression Flatten Optimized)
               ->  Sort
                     Sort Key: t1.a, t1.b
                     ->  Seq Scan on t1
               ->  Sort
                     Sort Key: t11.a, t11.b
                     ->  Seq Scan on t1 t11
               SubPlan 1
                 ->  Seq Scan on t3
                       Filter: (t1.a = a), (Expression Flatten Optimized)
               SubPlan 2
                 ->  Seq Scan on t3
(18 rows)
```
