PostgreSQL在何处处理 sql查询之七

前面已经说过,exec_simple_query要运行 PortalStart和 PortalRun。

可以说,PortalRun是重头戏,sql的真正执行,就在这里完成。

/*

 * PortalRun

 *        Run a portal's query or queries.

 *

 * count <= 0 is interpreted as a no-op: the destination gets started up

 * and shut down, but nothing else happens.  Also, count == FETCH_ALL is

 * interpreted as "all rows".  Note that count is ignored in multi-query

 * situations, where we always run the portal to completion.

 *

 * isTopLevel: true if query is being executed at backend "top level"

 * (that is, directly from a client command message)

 *

 * dest: where to send output of primary (canSetTag) query

 *

 * altdest: where to send output of non-primary queries

 *

 * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE

 *        in which to store a command completion status string.

 *        May be NULL if caller doesn't want a status string.

 *

 * Returns TRUE if the portal's execution is complete, FALSE if it was

 * suspended due to exhaustion of the count parameter.

 */

bool

PortalRun(Portal portal, long count, bool isTopLevel,

          DestReceiver *dest, DestReceiver *altdest,

          char *completionTag)

{

  ...

    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:



                /*

                 * If we have not yet run the command, do so, storing its

                 * results in the portal's tuplestore.  But we don't do that

                 * for the PORTAL_ONE_SELECT case.

                 */

                if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)

                    FillPortalStore(portal, isTopLevel);



                /*

                 * Now fetch desired portion of results.

                 */ nprocessed = PortalRunSelect(portal, true, count, dest); /*

                 * If the portal result contains a command tag and the caller

                 * gave us a pointer to store it, copy it. Patch the "SELECT"

                 * tag to also provide the rowcount.

                 */

                if (completionTag && portal->commandTag)

                {

                    if (strcmp(portal->commandTag, "SELECT") == 0)

                        snprintf(completionTag, COMPLETION_TAG_BUFSIZE,

                                 "SELECT %u", nprocessed);

                    else

                        strcpy(completionTag, portal->commandTag);

                }



                /* Mark portal not active */

                portal->status = PORTAL_READY;



                /*

                 * Since it's a forward fetch, say DONE iff atEnd is now true.

                 */

                result = portal->atEnd;

                break;



            case PORTAL_MULTI_QUERY:

                PortalRunMulti(portal, isTopLevel,

                               dest, altdest, completionTag);



                /* Prevent portal's commands from being re-executed */

                MarkPortalDone(portal);



                /* Always complete at end of RunMulti */

                result = true;

                break;



            default:

                elog(ERROR, "unrecognized portal strategy: %d",

                     (int) portal->strategy);

                result = false; /* keep compiler quiet */

                break;

        }

    }

    PG_CATCH();

    {

     ...

        PG_RE_THROW();

    }

    PG_END_TRY();

    ...

    return result;

}

这里面,这一段是核心:

                /*

                 * Now fetch desired portion of results.

                 */

                nprocessed = PortalRunSelect(portal, true, count, dest);

 

你可能感兴趣的:(PostgreSQL)