zoukankan      html  css  js  c++  java
  • PostgreSQL在何处处理 sql查询之二十六

    接前面,再次上溯一个层次,看代码(planmain.c :query_planner):

    void
    query_planner(PlannerInfo *root, List *tlist,
                  double tuple_fraction, double limit_tuples,
                  Path **cheapest_path, Path **sorted_path,
                  double *num_groups)
    {
       ...
    
        /*
         * Make a flattened version of the rangetable for faster access (this is
         * OK because the rangetable won't change any more), and set up an empty
         * array for indexing base relations.
         */
        setup_simple_rel_arrays(root);
    
        /*
         * Construct RelOptInfo nodes for all base relations in query, and
         * indirectly for all appendrel member relations ("other rels").  This
         * will give us a RelOptInfo for every "simple" (non-join) rel involved in
         * the query.
         *
         * Note: the reason we find the rels by searching the jointree and
         * appendrel list, rather than just scanning the rangetable, is that the
         * rangetable may contain RTEs for rels not actively part of the query,
         * for example views.  We don't want to make RelOptInfos for them.
         */
        add_base_rels_to_query(root, (Node *) parse->jointree);
        /*
         * Examine the targetlist and join tree, adding entries to baserel
         * targetlists for all referenced Vars, and generating PlaceHolderInfo
         * entries for all referenced PlaceHolderVars.    Restrict and join clauses
         * are added to appropriate lists belonging to the mentioned relations. We
         * also build EquivalenceClasses for provably equivalent expressions. The
         * SpecialJoinInfo list is also built to hold information about join order
         * restrictions.  Finally, we form a target joinlist for make_one_rel() to
         * work from.
         */
        build_base_rel_tlists(root, tlist);
    
        find_placeholders_in_jointree(root);
    
        joinlist = deconstruct_jointree(root);
    
        /*
         * Reconsider any postponed outer-join quals now that we have built up
         * equivalence classes.  (This could result in further additions or
         * mergings of classes.)
         */
        reconsider_outer_join_clauses(root);
    
        /*
         * If we formed any equivalence classes, generate additional restriction
         * clauses as appropriate.    (Implied join clauses are formed on-the-fly
         * later.)
         */
        generate_base_implied_equalities(root);
    
        /*
         * We have completed merging equivalence sets, so it's now possible to
         * convert previously generated pathkeys (in particular, the requested
         * query_pathkeys) to canonical form.
         */
        canonicalize_all_pathkeys(root);
    
        /*
         * Examine any "placeholder" expressions generated during subquery pullup.
         * Make sure that the Vars they need are marked as needed at the relevant
         * join level.    This must be done before join removal because it might
         * cause Vars or placeholders to be needed above a join when they weren't
         * so marked before.
         */
        fix_placeholder_input_needed_levels(root);
    
        /*
         * Remove any useless outer joins.    Ideally this would be done during
         * jointree preprocessing, but the necessary information isn't available
         * until we've built baserel data structures and classified qual clauses.
         */
        joinlist = remove_useless_joins(root, joinlist);
    
        /*
         * Now distribute "placeholders" to base rels as needed.  This has to be
         * done after join removal because removal could change whether a
         * placeholder is evaluatable at a base rel.
         */
        add_placeholders_to_base_rels(root);
        ...
    }

    在此处,setup_simple_rel_arrays 构造了指向指针的数组(其实是指向指针数组的指针),挂在root下。 add_base_rels_to_query 要利用此数组。

    看其中的代码(relnode.c):

    /*
     * setup_simple_rel_arrays
     *      Prepare the arrays we use for quickly accessing base relations.
     */
    void
    setup_simple_rel_arrays(PlannerInfo *root)
    {
        Index        rti;
        ListCell   *lc;
    
        /* Arrays are accessed using RT indexes (1..N) */
        root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
    
        /* simple_rel_array is initialized to all NULLs */
        root->simple_rel_array = (RelOptInfo **)
            palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
        ...
        
    }

    add_base_rels_to_query :(initsplan.c)

    void
    add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
    {
        if (jtnode == NULL)
            return;
        if (IsA(jtnode, RangeTblRef))
        {
            int    varno = ((RangeTblRef *) jtnode)->rtindex;
            (void) build_simple_rel(root, varno, RELOPT_BASEREL);
        }
        else if (IsA(jtnode, FromExpr))
        {
            FromExpr   *f = (FromExpr *) jtnode;
            ListCell   *l;
    
            foreach(l, f->fromlist)
                add_base_rels_to_query(root, lfirst(l));
        }
        else if (IsA(jtnode, JoinExpr))
        {
            JoinExpr   *j = (JoinExpr *) jtnode;
    
            add_base_rels_to_query(root, j->larg);
            add_base_rels_to_query(root, j->rarg);
        }
        else
            elog(ERROR, "unrecognized node type: %d",
                 (int) nodeTag(jtnode));
    }

    build_simple_rel:

    RelOptInfo *
    build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
    {
        RelOptInfo *rel;
        RangeTblEntry *rte;
    
    /* Rel should not exist already */ Assert(relid > 0 && relid < root->simple_rel_array_size); if (root->simple_rel_array[relid] != NULL) elog(ERROR, "rel %d already exists", relid); ... /* Check type of rtable entry */ switch (rte->rtekind) { case RTE_RELATION: /* Table --- retrieve statistics from the system catalogs */ get_relation_info(root, rte->relid, rte->inh, rel); break; case RTE_SUBQUERY: case RTE_FUNCTION: case RTE_VALUES: case RTE_CTE: /* * Subquery, function, or values list --- set up attr range and * arrays * * Note: 0 is included in range to support whole-row Vars */ rel->min_attr = 0; rel->max_attr = list_length(rte->eref->colnames); rel->attr_needed = (Relids *) palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids)); rel->attr_widths = (int32 *) palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32)); break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); break; } /* Save the finished struct in the query's simple_rel_array */ root->simple_rel_array[relid] = rel; ... return rel; }
  • 相关阅读:
    第一章 简介(待续)
    第十六章 漫话网站架构师(待续)
    第十五章 网站架构师职场攻略(待续)
    第十四章 架构师领导艺术(待续)
    第十三章 大型网站典型故障分析案例(待续)
    上帝造题的七分钟2/花神游历各国/GSS4 线段树维护区间开方 By cellur925
    LuoguP1606 [USACO07FEB]荷叶塘Lilypad Pond 【最短路】By cellur925
    NOIp2013 车站分级 【拓扑排序】By cellur925
    NOI题库--盒子和小球系列 By cellur925
    关于对动态规划的思考 【转】
  • 原文地址:https://www.cnblogs.com/gaojian/p/3103937.html
Copyright © 2011-2022 走看看