iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中Review subquery_planner函数的实现逻辑是什么
  • 519
分享到

PostgreSQL中Review subquery_planner函数的实现逻辑是什么

2024-04-02 19:04:59 519人浏览 安东尼
摘要

本篇内容介绍了“postgresql中Review subquery_planner函数的实现逻辑是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理

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

一、源码解读

subquery_planner函数由函数standard_planner调用,生成最终的结果Relation(成本最低),其输出作为生成实际执行计划的输入,在此函数中会调用grouping_planner执行主要的计划过程



PlannerInfo *
subquery_planner(PlannerGlobal *glob, Query *parse,
                 PlannerInfo *parent_root,
                 bool hasRecursion, double tuple_fraction)
{
    PlannerInfo *root;//返回值
    List       *newWithCheckOptions;//
    List       *newHaving;//Having子句
    bool        hasOuterJoins;//是否存在Outer Join?
    RelOptInfo *final_rel;//
    ListCell   *l;//临时变量

    
    //创建一个规划器数据结构:PlannerInfo
    root = makenode(PlannerInfo);//构造返回值
    root->parse = parse;
    root->glob = glob;
    root->query_level = parent_root ? parent_root->query_level + 1 : 1;
    root->parent_root = parent_root;
    root->plan_params = NIL;
    root->outer_params = NULL;
    root->planner_cxt = CurrentMemoryContext;
    root->init_plans = NIL;
    root->cte_plan_ids = NIL;
    root->multiexpr_params = NIL;
    root->eq_classes = NIL;
    root->append_rel_list = NIL;
    root->rowMarks = NIL;
    memset(root->upper_rels, 0, sizeof(root->upper_rels));
    memset(root->upper_targets, 0, sizeof(root->upper_targets));
    root->processed_tlist = NIL;
    root->grouping_map = NULL;
    root->minmax_aggs = NIL;
    root->qual_security_level = 0;
    root->inhTargetKind = INHKIND_NONE;
    root->hasRecursion = hasRecursion;
    if (hasRecursion)
        root->wt_param_id = SS_assign_special_param(root);
    else
        root->wt_param_id = -1;
    root->non_recursive_path = NULL;
    root->partColsUpdated = false;

    
    if (parse->cteList)
        SS_process_ctes(root);//处理With 语句

    
    if (parse->hasSubLinks)
        pull_up_sublinks(root); //上拉子链接

    
    inline_set_returning_functions(root);//

    
    pull_up_subqueries(root);//上拉子查询

    
    if (parse->setOperations)
        flatten_simple_uNIOn_all(root);//扁平化处理UNION ALL

    
     //判断RTE中是否存在RTE_JOIN?
    root->hasJoinRTEs = false;
    root->hasLateralRTEs = false;
    hasOuterJoins = false;
    foreach(l, parse->rtable)
    {
        RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);

        if (rte->rtekind == RTE_JOIN)
        {
            root->hasJoinRTEs = true;
            if (IS_OUTER_JOIN(rte->jointype))
                hasOuterJoins = true;
        }
        if (rte->lateral)
            root->hasLateralRTEs = true;
    }

    
     //预处理RowMark信息
    preprocess_rowmarks(root);

    
     //展开继承表
    expand_inherited_tables(root);

    
     //是否存在Having表达式
    root->hasHavingQual = (parse->havingQual != NULL);

    
    //清除hasPseudoConstantQuals标记,该标记可能在distribute_qual_to_rels函数中设置
    root->hasPseudoConstantQuals = false;

    
     //预处理表达式:targetList(投影列)
    parse->targetList = (List *)
        preprocess_expression(root, (Node *) parse->targetList,
                              EXPRKIND_TARGET);

    
    //Constant-folding 可能已经把set-returning函数去掉
    if (parse->hasTargetSRFs)
        parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);

    newWithCheckOptions = NIL;
    foreach(l, parse->withCheckOptions)//witch Check Options
    {
        WithCheckOption *wco = lfirst_node(WithCheckOption, l);

        wco->qual = preprocess_expression(root, wco->qual,
                                          EXPRKIND_QUAL);
        if (wco->qual != NULL)
            newWithCheckOptions = lappend(newWithCheckOptions, wco);
    }
    parse->withCheckOptions = newWithCheckOptions;
     //返回列信息returningList
    parse->returningList = (List *)
        preprocess_expression(root, (Node *) parse->returningList,
                              EXPRKIND_TARGET);
     //预处理条件表达式
    preprocess_qual_conditions(root, (Node *) parse->jointree);
     //预处理Having表达式
    parse->havingQual = preprocess_expression(root, parse->havingQual,
                                              EXPRKIND_QUAL);
     //窗口函数
    foreach(l, parse->windowClause)
    {
        WindowClause *wc = lfirst_node(WindowClause, l);

        
        wc->startOffset = preprocess_expression(root, wc->startOffset,
                                                EXPRKIND_LIMIT);
        wc->endOffset = preprocess_expression(root, wc->endOffset,
                                              EXPRKIND_LIMIT);
    }
     //Limit子句
    parse->limitOffset = preprocess_expression(root, parse->limitOffset,
                                               EXPRKIND_LIMIT);
    parse->limitCount = preprocess_expression(root, parse->limitCount,
                                              EXPRKIND_LIMIT);
     //On Conflict子句
    if (parse->onConflict)
    {
        parse->onConflict->arbiterElems = (List *)
            preprocess_expression(root,
                                  (Node *) parse->onConflict->arbiterElems,
                                  EXPRKIND_ARBITER_ELEM);
        parse->onConflict->arbiterWhere =
            preprocess_expression(root,
                                  parse->onConflict->arbiterWhere,
                                  EXPRKIND_QUAL);
        parse->onConflict->onConflictSet = (List *)
            preprocess_expression(root,
                                  (Node *) parse->onConflict->onConflictSet,
                                  EXPRKIND_TARGET);
        parse->onConflict->onConflictWhere =
            preprocess_expression(root,
                                  parse->onConflict->onConflictWhere,
                                  EXPRKIND_QUAL);
        
    }
     //集合操作(AppendRelInfo)
    root->append_rel_list = (List *)
        preprocess_expression(root, (Node *) root->append_rel_list,
                              EXPRKIND_APPINFO);
     //RTE
    
    foreach(l, parse->rtable)
    {
        RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
        int         kind;
        ListCell   *lcsq;

        if (rte->rtekind == RTE_RELATION)
        {
            if (rte->tablesample)
                rte->tablesample = (TableSampleClause *)
                    preprocess_expression(root,
                                          (Node *) rte->tablesample,
                                          EXPRKIND_TABLESAMPLE);//数据表采样语句
        }
        else if (rte->rtekind == RTE_SUBQUERY)//子查询
        {
            
            if (rte->lateral && root->hasJoinRTEs)
                rte->subquery = (Query *)
                    flatten_join_alias_vars(root, (Node *) rte->subquery);
        }
        else if (rte->rtekind == RTE_FUNCTION)//函数
        {
            
            //预处理函数表达式
            kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
            rte->functions = (List *)
                preprocess_expression(root, (Node *) rte->functions, kind);
        }
        else if (rte->rtekind == RTE_TABLEFUNC)//TABLE FUNC
        {
            
            kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC;
            rte->tablefunc = (TableFunc *)
                preprocess_expression(root, (Node *) rte->tablefunc, kind);
        }
        else if (rte->rtekind == RTE_VALUES)//VALUES子句
        {
            
            kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
            rte->values_lists = (List *)
                preprocess_expression(root, (Node *) rte->values_lists, kind);
        }

        
        foreach(lcsq, rte->securityQuals)
        {
            lfirst(lcsq) = preprocess_expression(root,
                                                 (Node *) lfirst(lcsq),
                                                 EXPRKIND_QUAL);
        }
    }

    
    if (root->hasJoinRTEs)
    {
        foreach(l, parse->rtable)
        {
            RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);

            rte->joinaliasvars = NIL;
        }
    }

    
    newHaving = NIL;
    foreach(l, (List *) parse->havingQual)
    {
        Node       *havingclause = (Node *) lfirst(l);

        if ((parse->groupClause && parse->groupingSets) ||
            contain_agg_clause(havingclause) ||
            contain_volatile_functions(havingclause) ||
            contain_subplans(havingclause))
        {
            
            newHaving = lappend(newHaving, havingclause);
        }
        else if (parse->groupClause && !parse->groupingSets)
        {
            
            parse->jointree->quals = (Node *)
                lappend((List *) parse->jointree->quals, havingclause);
        }
        else
        {
            
            parse->jointree->quals = (Node *)
                lappend((List *) parse->jointree->quals,
                        copyObject(havingclause));
            newHaving = lappend(newHaving, havingclause);
        }
    }
    parse->havingQual = (Node *) newHaving;

    
    //移除多余的GROUP BY 列
    remove_useless_groupby_columns(root);

    
    if (hasOuterJoins)
        reduce_outer_joins(root);

    
    if (parse->resultRelation &&
        rt_fetch(parse->resultRelation, parse->rtable)->inh)
        inheritance_planner(root);
    else
        grouping_planner(root, false, tuple_fraction);

    
    SS_identify_outer_params(root);

    
    final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
    SS_charge_for_initplans(root, final_rel);

    
    set_cheapest(final_rel);

    return root;
}

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

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中Review subquery_planner函数的实现逻辑是什么

本文链接: https://www.lsjlt.com/news/64785.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作