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

    回溯:PortalRun --> PortalRunSelect

    bool
    PortalRun(Portal portal, long count, bool isTopLevel,
              DestReceiver *dest, DestReceiver *altdest,
              char *completionTag)
    {
        ...
        portal->status = PORTAL_ACTIVE;
        ...
        PG_TRY();
        {
            ActivePortal = portal;
            CurrentResourceOwner = portal->resowner;
            PortalContext = PortalGetHeapMemory(portal);
    
            MemoryContextSwitchTo(PortalContext);
    
            switch (portal->strategy)
            {
                case PORTAL_ONE_SELECT:
                case PORTAL_ONE_RETURNING:
                case PORTAL_ONE_MOD_WITH:
                case PORTAL_UTIL_SELECT:
                    ...
                    /*
                     * Now fetch desired portion of results.
                     */
                    nprocessed = PortalRunSelect(portal, true, count, dest);
                    ...
                    break;
    
                case PORTAL_MULTI_QUERY:
                    ...
                    break;
    
                default:
                    ...
                    break;
            }
        }
        PG_CATCH();
        {
            ...
            PG_RE_THROW();
        }
        PG_END_TRY();
        ...
        return result;
    }

    再回溯:

    static void
    exec_simple_query(const char *query_string)
    {
        ...
        parsetree_list = pg_parse_query(query_string);
        ...
        /*
         * Run through the raw parsetree(s) and process each one.
         */
        foreach(parsetree_item, parsetree_list)
        {
            ...
            querytree_list = pg_analyze_and_rewrite(parsetree, query_string,NULL, 0);
            plantree_list = pg_plan_queries(querytree_list, 0, NULL);
            ...
            portal = CreatePortal("", true, true);
            ...
            PortalDefineQuery(portal,
                              NULL,
                              query_string,
                              commandTag,
                              plantree_list,
                              NULL);
            ...
            PortalStart(portal, NULL, 0, snapshot_set);
            ...
            /*
             * Run the portal to completion, and then drop it (and the receiver).
             */
            (void) PortalRun(portal,
                             FETCH_ALL,
                             isTopLevel,
                             receiver,
                             receiver,
                             completionTag);
    
            ...
        }                            /* end loop over parsetrees */
        ...
    }

     从源代码中查看的结果是:对于我的普通查询,InitScanRelation中对 ss_currentScanDesc 进行了赋值。

    经过调查,路径是这样的:

    PortalStart-->ExecutorStart-->Standard_ExecutorStart-->InitPlan-->ExecInitNode-->ExecInitSeqscan-->InitScanRelation

    再回过头来回味:

    PlanState *
    ExecInitNode(Plan *node, EState *estate, int eflags)
    {
        PlanState  *result;
        List       *subps;
        ListCell   *l;
    
        /*
         * do nothing when we get to the end of a leaf on tree.
         */
        if (node == NULL)
            return NULL;
    
        switch (nodeTag(node))
        {
                /*
                 * control nodes
                 */
            case T_Result:
                result = (PlanState *) ExecInitResult((Result *) node,
                                                      estate, eflags);
                break;
    
            ..
    
                /*
                 * scan nodes
                 */
            case T_SeqScan:
                result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
                                                       estate, eflags);
                break;
    
            case T_IndexScan:
                result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
                                                         estate, eflags);
                break;
    
            case T_IndexOnlyScan:
                result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
                                                             estate, eflags);
                break;
    
            ...
        }
    
        /*
         * Initialize any initPlans present in this node.  The planner put them in
         * a separate list for us.
         */
        subps = NIL;
        foreach(l, node->initPlan)
        {
            SubPlan    *subplan = (SubPlan *) lfirst(l);
            SubPlanState *sstate;
    
            Assert(IsA(subplan, SubPlan));
            sstate = ExecInitSubPlan(subplan, result);
            subps = lappend(subps, sstate);
        }
        result->initPlan = subps;
    
        /* Set up instrumentation for this node if requested */
        if (estate->es_instrument)
            result->instrument = InstrAlloc(1, estate->es_instrument);
    
        return result;
    }

    从上面可以看到,在进行  ExecInitNode 的时候,根据tag 进行了特定的初始化。

    ExecInitSeqscan:

    /* ----------------------------------------------------------------
     *        ExecInitSeqScan
     * ----------------------------------------------------------------
     */
    SeqScanState *
    ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
    {
        SeqScanState *scanstate;
    
        /*
         * Once upon a time it was possible to have an outerPlan of a SeqScan, but
         * not any more.
         */
        Assert(outerPlan(node) == NULL);
        Assert(innerPlan(node) == NULL);
    
        /*
         * create state structure
         */
        scanstate = makeNode(SeqScanState);
        scanstate->ps.plan = (Plan *) node;
        scanstate->ps.state = estate;
    
        /*
         * Miscellaneous initialization
         *
         * create expression context for node
         */
        ExecAssignExprContext(estate, &scanstate->ps);
    
        /*
         * initialize child expressions
         */
        scanstate->ps.targetlist = (List *)
            ExecInitExpr((Expr *) node->plan.targetlist,
                         (PlanState *) scanstate);
        scanstate->ps.qual = (List *)
            ExecInitExpr((Expr *) node->plan.qual,
                         (PlanState *) scanstate);
    
        /*
         * tuple table initialization
         */
        ExecInitResultTupleSlot(estate, &scanstate->ps);
        ExecInitScanTupleSlot(estate, scanstate);
    
        /*
         * initialize scan relation
         */
        InitScanRelation(scanstate, estate);
    
        scanstate->ps.ps_TupFromTlist = false;
    
        /*
         * Initialize result tuple type and projection info.
         */
        ExecAssignResultTypeFromTL(&scanstate->ps);
        ExecAssignScanProjectionInfo(scanstate);
    
        return scanstate;
    }

     与此相对的,还有另外一条路径,非常类似:

    PortalRun-->

    PortalRunSelect-->ExecutorRun-->Standard_ExecutorRun-->ExecutePlan-->ExecProcNode-->ExecSeqscan

    当初在 PortalStart 的时候按 Tag来分别进行初始化,在 PortalRun的时候,也要按照 Tag 来分别执行各自合适的Scan(物理磁盘扫描)。

    TupleTableSlot *
    ExecProcNode(PlanState *node)
    {
    
        TupleTableSlot *result;
    
        CHECK_FOR_INTERRUPTS();
    
        if (node->chgParam != NULL) /* something changed */
            ExecReScan(node);        /* let ReScan handle this */
    
        if (node->instrument)
            InstrStartNode(node->instrument);
    
        switch (nodeTag(node))
        {
                /*
                 * control nodes
                 */
            case T_ResultState:
                result = ExecResult((ResultState *) node);
                break;
    
            ...
    
                /*
                 * scan nodes
                 */
            case T_SeqScanState:
                result = ExecSeqScan((SeqScanState *) node);
                break;
    
            ...
        }
    
        if (node->instrument)
            InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
    
        return result;
    }
  • 相关阅读:
    70.BOM
    69.捕获错误try catch
    68.键盘事件
    523. Continuous Subarray Sum
    901. Online Stock Span
    547. Friend Circles
    162. Find Peak Element
    1008. Construct Binary Search Tree from Preorder Traversal
    889. Construct Binary Tree from Preorder and Postorder Traversal
    106. Construct Binary Tree from Inorder and Postorder Traversal
  • 原文地址:https://www.cnblogs.com/gaojian/p/3115284.html
Copyright © 2011-2022 走看看