文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中函数reconsider_outer_join_clauses的主要实现逻辑是什么

2024-04-02 19:55

关注

本篇内容介绍了“PostgreSQL中函数reconsider_outer_join_clauses的主要实现逻辑是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

query_planner代码片段:

     //...
     
     build_base_rel_tlists(root, tlist);//构建"base rels"的投影列
 
     find_placeholders_in_jointree(root);//处理jointree中的PHI
 
     find_lateral_references(root);//处理jointree中Lateral依赖
 
     joinlist = deconstruct_jointree(root);//分解jointree

     
     reconsider_outer_join_clauses(root);//已创建等价类,那么需要重新考虑被下推后处理的外连接表达式
 
     
     generate_base_implied_equalities(root);//等价类构建后,生成因此外加的约束语句
 
     //...

一、重要的数据结构

RelOptInfo
与上节一样,RelOptInfo结构体贯彻逻辑优化和物理优化过程的始终,需不时Review.

 typedef struct RelOptInfo
 {
     NodeTag     type;//节点标识
 
     RelOptKind  reloptkind;//RelOpt类型
 
     
     Relids      relids;         
 
     
     double      rows;           
 
     
     bool        consider_startup;   
     bool        consider_param_startup; 
     bool        consider_parallel;  
 
     
     struct PathTarget *reltarget;   
 
     
     List       *pathlist;       
     List       *ppilist;        
     List       *partial_pathlist;   
     struct Path *cheapest_startup_path;//代价最低的启动路径
     struct Path *cheapest_total_path;//代价最低的整体路径
     struct Path *cheapest_unique_path;//代价最低的获取唯一值的路径
     List       *cheapest_parameterized_paths;//代价最低的参数化?路径链表
 
     
     
     Relids      direct_lateral_relids;  
     Relids      lateral_relids; 
 
     
     //reloptkind=RELOPT_BASEREL时使用的数据结构
     Index       relid;          
     Oid         reltablespace;  
     RTEKind     rtekind;        
     AttrNumber  min_attr;       
     AttrNumber  max_attr;       
     Relids     *attr_needed;    
     int32      *attr_widths;    
     List       *lateral_vars;   
     Relids      lateral_referencers;    
     List       *indexlist;      
     List       *statlist;       
     BlockNumber pages;          
     double      tuples;         
     double      allvisfrac;     
     PlannerInfo *subroot;       
     List       *subplan_params; 
     int         rel_parallel_workers;   
 
     
     //FWD相关信息
     Oid         serverid;       
     Oid         userid;         
     bool        useridiscurrent;    
     
     struct FdwRoutine *fdwroutine;
     void       *fdw_private;
 
     
     //已知的,可保证唯一的Relids链表
     List       *unique_for_rels;    
     List       *non_unique_for_rels;    
 
     
     List       *baserestrictinfo;   
     QualCost    baserestrictcost;   
     Index       baserestrict_min_security;  
     List       *joininfo;       
     bool        has_eclass_joins;   
 
     
     bool        consider_partitionwise_join;    
     Relids      top_parent_relids;  
 
     
     //分区表使用
     PartitionScheme part_scheme;    
     int         nparts;         
     struct PartitionBoundInfoData *boundinfo;   
     List       *partition_qual; 
     struct RelOptInfo **part_rels;  
     List      **partexprs;      
     List      **nullable_partexprs; 
     List       *partitioned_child_rels; 
 } RelOptInfo;

二、源码解读

reconsider_outer_join_clauses函数
该函数遍历优化器信息(PlannerInfo)中的外连接子句(left_join_clauses),把条件分发到合适的地方,其中限制条件(Where子句中的条件)分发到RelOptInfo->baserestrictinfo中,连接条件(连接语句中的条件ON XX)分发到joininfo中

  
 void
 reconsider_outer_join_clauses(PlannerInfo *root)
 {
     bool        found;
     ListCell   *cell;
     ListCell   *prev;
     ListCell   *next;
 
     
     do
     {
         found = false;
 
         
         prev = NULL;
         for (cell = list_head(root->left_join_clauses); cell; cell = next)//遍历left_join_clauses
         {
             RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
             next = lnext(cell);
             if (reconsider_outer_join_clause(root, rinfo, true))
             {
                 found = true;
                 
                 root->left_join_clauses =
                     list_delete_cell(root->left_join_clauses, cell, prev);//如可以,则去掉连接条件(移到约束条件中)
                 
                 
                 rinfo->norm_selec = 2.0;
                 rinfo->outer_selec = 1.0;
                 distribute_restrictinfo_to_rels(root, rinfo);//分发到RelOptInfo中
             }
             else
                 prev = cell;
         }
 
         
         prev = NULL;
         for (cell = list_head(root->right_join_clauses); cell; cell = next)//处理右连接
         {
             RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
             next = lnext(cell);
             if (reconsider_outer_join_clause(root, rinfo, false))
             {
                 found = true;
                 
                 root->right_join_clauses =
                     list_delete_cell(root->right_join_clauses, cell, prev);
                 
                 
                 rinfo->norm_selec = 2.0;
                 rinfo->outer_selec = 1.0;
                 distribute_restrictinfo_to_rels(root, rinfo);
             }
             else
                 prev = cell;
         }
 
         
         prev = NULL;
         for (cell = list_head(root->full_join_clauses); cell; cell = next)//全连接
         {
             RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
             next = lnext(cell);
             if (reconsider_full_join_clause(root, rinfo))
             {
                 found = true;
                 
                 root->full_join_clauses =
                     list_delete_cell(root->full_join_clauses, cell, prev);
                 
                 
                 rinfo->norm_selec = 2.0;
                 rinfo->outer_selec = 1.0;
                 distribute_restrictinfo_to_rels(root, rinfo);
             }
             else
                 prev = cell;
         }
     } while (found);
   //处理连接条件链表中余下的条件
     
     foreach(cell, root->left_join_clauses)
     {
         RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
         distribute_restrictinfo_to_rels(root, rinfo);
     }
     foreach(cell, root->right_join_clauses)
     {
         RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
         distribute_restrictinfo_to_rels(root, rinfo);
     }
     foreach(cell, root->full_join_clauses)
     {
         RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell);
 
         distribute_restrictinfo_to_rels(root, rinfo);
     }
 }
 
 
 static bool
 reconsider_outer_join_clause(PlannerInfo *root, RestrictInfo *rinfo,
                              bool outer_on_left)
 {
     Expr       *outervar,
                *innervar;
     Oid         opno,
                 collation,
                 left_type,
                 right_type,
                 inner_datatype;
     Relids      inner_relids,
                 inner_nullable_relids;
     ListCell   *lc1;
 
     Assert(is_opclause(rinfo->clause));
     opno = ((OpExpr *) rinfo->clause)->opno;
     collation = ((OpExpr *) rinfo->clause)->inputcollid;
 
     
     if (rinfo->outerjoin_delayed && !op_strict(opno))
         return false;
 
     
     op_input_types(opno, &left_type, &right_type);
     if (outer_on_left)
     {
         outervar = (Expr *) get_leftop(rinfo->clause);
         innervar = (Expr *) get_rightop(rinfo->clause);
         inner_datatype = right_type;
         inner_relids = rinfo->right_relids;
     }
     else
     {
         outervar = (Expr *) get_rightop(rinfo->clause);
         innervar = (Expr *) get_leftop(rinfo->clause);
         inner_datatype = left_type;
         inner_relids = rinfo->left_relids;
     }
     inner_nullable_relids = bms_intersect(inner_relids,
                                           rinfo->nullable_relids);
 
     
     foreach(lc1, root->eq_classes)//遍历等价类
     {
         EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
         bool        match;
         ListCell   *lc2;
 
         
         if (!cur_ec->ec_has_const)
             continue;
         
         if (cur_ec->ec_has_volatile)
             continue;
         
         if (collation != cur_ec->ec_collation)
             continue;
         if (!equal(rinfo->mergeopfamilies, cur_ec->ec_opfamilies))
             continue;
         
         match = false;
         foreach(lc2, cur_ec->ec_members)
         {
             EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
 
             Assert(!cur_em->em_is_child);   
             if (equal(outervar, cur_em->em_expr))
             {
                 match = true;
                 break;
             }
         }
         if (!match)
             continue;           
 
         
         match = false;
         foreach(lc2, cur_ec->ec_members)
         {
             EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
             Oid         eq_op;
             RestrictInfo *newrinfo;
 
             if (!cur_em->em_is_const)
                 continue;       
             eq_op = select_equality_operator(cur_ec,
                                              inner_datatype,
                                              cur_em->em_datatype);
             if (!OidIsValid(eq_op))
                 continue;       
             newrinfo = build_implied_join_equality(eq_op,
                                                    cur_ec->ec_collation,
                                                    innervar,
                                                    cur_em->em_expr,
                                                    bms_copy(inner_relids),
                                                    bms_copy(inner_nullable_relids),
                                                    cur_ec->ec_min_security);
             if (process_equivalence(root, &newrinfo, true))
                 match = true;
         }
 
         
         if (match)
             return true;
         else
             break;
     }
 
     return false;               
 }

generate_base_implied_equalities函数
该函数遍历所有的等价类,找出一个隐含的条件然后分发到RelOptInfo中,这样做的目的是为了在连接(join)前过滤元组,减少参与运算的元组数量.


 void
 generate_base_implied_equalities(PlannerInfo *root)
 {
     ListCell   *lc;
     Index       rti;
 
     foreach(lc, root->eq_classes)//遍历等价类
     {
         EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc);
 
         Assert(ec->ec_merged == NULL);  
         Assert(!ec->ec_broken); 
 
         
         if (list_length(ec->ec_members) <= 1)//小于1个成员,无需处理类
             continue;
 
         if (ec->ec_has_const)//有常量
             generate_base_implied_equalities_const(root, ec);
         else//无常量
             generate_base_implied_equalities_no_const(root, ec);
 
         
         if (ec->ec_broken)//处理失败个案
             generate_base_implied_equalities_broken(root, ec);
     }
 
     
     for (rti = 1; rti < root->simple_rel_array_size; rti++)//设置标记
     {
         RelOptInfo *brel = root->simple_rel_array[rti];
 
         if (brel == NULL)
             continue;
 
         brel->has_eclass_joins = has_relevant_eclass_joinclause(root, brel);
     }
 }
 
 
 static void
 generate_base_implied_equalities_const(PlannerInfo *root,
                                        EquivalenceClass *ec)
 {
     EquivalenceMember *const_em = NULL;
     ListCell   *lc;
 
     
     if (list_length(ec->ec_members) == 2 &&
         list_length(ec->ec_sources) == 1)
     {
         RestrictInfo *restrictinfo = (RestrictInfo *) linitial(ec->ec_sources);
 
         if (bms_membership(restrictinfo->required_relids) != BMS_MULTIPLE)
         {
             distribute_restrictinfo_to_rels(root, restrictinfo);
             return;
         }
     }
 
     
     foreach(lc, ec->ec_members)//获取常量Member
     {
         EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
 
         if (cur_em->em_is_const)
         {
             const_em = cur_em;
             if (IsA(cur_em->em_expr, Const))
                 break;
         }
     }
     Assert(const_em != NULL);
 
     
     foreach(lc, ec->ec_members)
     {
         EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
         Oid         eq_op;
 
         Assert(!cur_em->em_is_child);   
         if (cur_em == const_em)
             continue;
         eq_op = select_equality_operator(ec,
                                          cur_em->em_datatype,
                                          const_em->em_datatype);
         if (!OidIsValid(eq_op))
         {
             
             ec->ec_broken = true;
             break;
         }
         process_implied_equality(root, eq_op, ec->ec_collation,
                                  cur_em->em_expr, const_em->em_expr,
                                  bms_copy(ec->ec_relids),
                                  bms_union(cur_em->em_nullable_relids,
                                            const_em->em_nullable_relids),
                                  ec->ec_min_security,
                                  ec->ec_below_outer_join,
                                  cur_em->em_is_const);//下推条件
     }
 }
 
 
 static void
 generate_base_implied_equalities_no_const(PlannerInfo *root,
                                           EquivalenceClass *ec)
 {
     EquivalenceMember **prev_ems;
     ListCell   *lc;
 
     
     prev_ems = (EquivalenceMember **)
         palloc0(root->simple_rel_array_size * sizeof(EquivalenceMember *));
 
     foreach(lc, ec->ec_members)
     {
         EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
         int         relid;
 
         Assert(!cur_em->em_is_child);   
         if (!bms_get_singleton_member(cur_em->em_relids, &relid))
             continue;
         Assert(relid < root->simple_rel_array_size);
 
         if (prev_ems[relid] != NULL)
         {
             EquivalenceMember *prev_em = prev_ems[relid];
             Oid         eq_op;
 
             eq_op = select_equality_operator(ec,
                                              prev_em->em_datatype,
                                              cur_em->em_datatype);
             if (!OidIsValid(eq_op))
             {
                 
                 ec->ec_broken = true;
                 break;
             }
             process_implied_equality(root, eq_op, ec->ec_collation,
                                      prev_em->em_expr, cur_em->em_expr,
                                      bms_copy(ec->ec_relids),
                                      bms_union(prev_em->em_nullable_relids,
                                                cur_em->em_nullable_relids),
                                      ec->ec_min_security,
                                      ec->ec_below_outer_join,
                                      false);
         }
         prev_ems[relid] = cur_em;
     }
 
     pfree(prev_ems);
 
     
     foreach(lc, ec->ec_members)
     {
         EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
         List       *vars = pull_var_clause((Node *) cur_em->em_expr,
                                            PVC_RECURSE_AGGREGATES |
                                            PVC_RECURSE_WINDOWFUNCS |
                                            PVC_INCLUDE_PLACEHOLDERS);
 
         add_vars_to_targetlist(root, vars, ec->ec_relids, false);
         list_free(vars);
     }
 }
 
 
 static void
 generate_base_implied_equalities_broken(PlannerInfo *root,
                                         EquivalenceClass *ec)
 {
     ListCell   *lc;
 
     foreach(lc, ec->ec_sources)
     {
         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
 
         if (ec->ec_has_const ||
             bms_membership(restrictinfo->required_relids) != BMS_MULTIPLE)
             distribute_restrictinfo_to_rels(root, restrictinfo);
     }
 }

 
 void
 process_implied_equality(PlannerInfo *root,
                          Oid opno,
                          Oid collation,
                          Expr *item1,
                          Expr *item2,
                          Relids qualscope,
                          Relids nullable_relids,
                          Index security_level,
                          bool below_outer_join,
                          bool both_const)
 {
     Expr       *clause;
 
     
     clause = make_opclause(opno,
                            BOOLOID, 
                            false,   
                            copyObject(item1),
                            copyObject(item2),
                            InvalidOid,
                            collation);//构造条件表达式
 
     
     if (both_const)//
     {
         clause = (Expr *) eval_const_expressions(root, (Node *) clause);
 
         
         if (clause && IsA(clause, Const))
         {
             Const      *cclause = (Const *) clause;
 
             Assert(cclause->consttype == BOOLOID);
             if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
                 return;
         }
     }
 
     
     distribute_qual_to_rels(root, (Node *) clause,
                             true, below_outer_join, JOIN_INNER,
                             security_level,
                             qualscope, NULL, NULL, nullable_relids,
                             NULL);//分发条件至RelOptInfo
 }

三、跟踪分析

测试脚本:

testdb=# explain verbose select t1.dwbh,t2.grbh
testdb-# from t_dwxx t1 left join t_grxx t2 on t1.dwbh = t2.dwbh and t2.dwbh = '1001' 
testdb-# order by t2.dwbh;
                                    QUERY PLAN                                     
-----------------------------------------------------------------------------------
 Sort  (cost=19.16..19.56 rows=160 width=114)
   Output: t1.dwbh, t2.grbh, t2.dwbh
   Sort Key: t2.dwbh
   ->  Hash Left Join  (cost=1.09..13.30 rows=160 width=114)
         Output: t1.dwbh, t2.grbh, t2.dwbh
         Hash Cond: ((t1.dwbh)::text = (t2.dwbh)::text)
         ->  Seq Scan on public.t_dwxx t1  (cost=0.00..11.60 rows=160 width=38)
               Output: t1.dwmc, t1.dwbh, t1.dwdz
         ->  Hash  (cost=1.07..1.07 rows=1 width=76)
               Output: t2.grbh, t2.dwbh
               ->  Seq Scan on public.t_grxx t2  (cost=0.00..1.07 rows=1 width=76)
                     Output: t2.grbh, t2.dwbh
                     Filter: ((t2.dwbh)::text = '1001'::text)
(13 rows)

跟踪分析,启动gdb

(gdb) b planmain.c:161
Breakpoint 1 at 0x76958b: file planmain.c, line 161.
(gdb) c
Continuing.

Breakpoint 1, query_planner (root=0x2c92a88, tlist=0x2c5f048, qp_callback=0x76e906 <standard_qp_callback>, 
    qp_extra=0x7fffed6e9c10) at planmain.c:163
warning: Source file is more recent than executable.
163   reconsider_outer_join_clauses(root);

调用前检查root(PlannerInfo)->simple_rel_array数组的内存结构,可以看到baserestrictinfo和joininfo均为NULL

(gdb) p *root->simple_rel_array[1]
$2 = {type = T_RelOptInfo, reloptkind = RELOPT_BASEREL, relids = 0x2c5fdd0, rows = 0, consider_startup = false, 
  consider_param_startup = false, consider_parallel = false, reltarget = 0x2c5fde8, pathlist = 0x0, ppilist = 0x0, 
  partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, 
  cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 1, reltablespace = 0, 
  rtekind = RTE_RELATION, min_attr = -7, max_attr = 3, attr_needed = 0x2c5fe38, attr_widths = 0x2c5fec8, 
  lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x2c60160, statlist = 0x0, pages = 10, tuples = 160, 
  allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers = -1, serverid = 0, userid = 0, 
  useridiscurrent = false, fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, 
  baserestrictinfo = 0x0, baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, 
  joininfo = 0x0, has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, 
  partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}
(gdb) p *root->simple_rel_array[2]
$3 = {type = T_RelOptInfo, reloptkind = RELOPT_BASEREL, relids = 0x2c60860, rows = 0, consider_startup = false, 
  consider_param_startup = false, consider_parallel = false, reltarget = 0x2c60878, pathlist = 0x0, ppilist = 0x0, 
  partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, 
  cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 2, reltablespace = 0, 
  rtekind = RTE_RELATION, min_attr = -7, max_attr = 5, attr_needed = 0x2c608c8, attr_widths = 0x2c60958, 
  lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 1, tuples = 6, allvisfrac = 0, 
  subroot = 0x0, subplan_params = 0x0, rel_parallel_workers = -1, serverid = 0, userid = 0, useridiscurrent = false, 
  fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x0, 
  baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x0, 
  has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, 
  part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}
(gdb)

调用reconsider_outer_join_clauses,注意joininfo,填入了相应的数据

(gdb) p *root->simple_rel_array[1]
$4 = {type = T_RelOptInfo, reloptkind = RELOPT_BASEREL, relids = 0x2c5fdd0, rows = 0, consider_startup = false, 
  consider_param_startup = false, consider_parallel = false, reltarget = 0x2c5fde8, pathlist = 0x0, ppilist = 0x0, 
  partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, 
  cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 1, reltablespace = 0, 
  rtekind = RTE_RELATION, min_attr = -7, max_attr = 3, attr_needed = 0x2c5fe38, attr_widths = 0x2c5fec8, 
  lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x2c60160, statlist = 0x0, pages = 10, tuples = 160, 
  allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers = -1, serverid = 0, userid = 0, 
  useridiscurrent = false, fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, 
  baserestrictinfo = 0x0, baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, 
  joininfo = 0x2c61780, has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, 
  partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}
(gdb) p *root->simple_rel_array[2]
$5 = {type = T_RelOptInfo, reloptkind = RELOPT_BASEREL, relids = 0x2c60860, rows = 0, consider_startup = false, 
  consider_param_startup = false, consider_parallel = false, reltarget = 0x2c60878, pathlist = 0x0, ppilist = 0x0, 
  partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, 
  cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 2, reltablespace = 0, 
  rtekind = RTE_RELATION, min_attr = -7, max_attr = 5, attr_needed = 0x2c608c8, attr_widths = 0x2c60958, 
  lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 1, tuples = 6, allvisfrac = 0, 
  subroot = 0x0, subplan_params = 0x0, rel_parallel_workers = -1, serverid = 0, userid = 0, useridiscurrent = false, 
  fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x0, 
  baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x2c617d0, 
  has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, 
  part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}

调用generate_base_implied_equalities,注意root->simple_rel_array[2]->baserestrictinfo,条件已下推至限制条件(原为连接条件)

(gdb) p *root->simple_rel_array[2]
$7 = {type = T_RelOptInfo, reloptkind = RELOPT_BASEREL, relids = 0x2c60860, rows = 0, consider_startup = false, 
  consider_param_startup = false, consider_parallel = false, reltarget = 0x2c60878, pathlist = 0x0, ppilist = 0x0, 
  partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, 
  cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 2, reltablespace = 0, 
  rtekind = RTE_RELATION, min_attr = -7, max_attr = 5, attr_needed = 0x2c608c8, attr_widths = 0x2c60958, 
  lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 1, tuples = 6, allvisfrac = 0, 
  subroot = 0x0, subplan_params = 0x0, rel_parallel_workers = -1, serverid = 0, userid = 0, useridiscurrent = false, 
  fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x2c61820, 
  baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 0, joininfo = 0x2c617d0, 
  has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, 
  part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}

“PostgreSQL中函数reconsider_outer_join_clauses的主要实现逻辑是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯