PostgreSQL在何处处理 sql查询之五

在定义了Portal之后,需要运行:PortalStart,它主要的任务是明确执行策略,然后再执行 ExecutorStart:

代码太长,进行缩略:

void
PortalStart(Portal portal, ParamListInfo params,
            int eflags, bool use_active_snapshot)
{
    ...
    PG_TRY();
    {
        ActivePortal = portal;
        CurrentResourceOwner = portal->resowner;
        PortalContext = PortalGetHeapMemory(portal);

        oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));

        /* Must remember portal param list, if any */
        portal->portalParams = params;

        /*
         * Determine the portal execution strategy
         */
        portal->strategy = ChoosePortalStrategy(portal->stmts);

        /*
         * Fire her up according to the strategy
         */
        switch (portal->strategy)
        {
            case PORTAL_ONE_SELECT:

          ...break;

            case PORTAL_ONE_RETURNING:
            case PORTAL_ONE_MOD_WITH:

          ...break;

            case PORTAL_UTIL_SELECT:

          ...break;

            case PORTAL_MULTI_QUERY:
          ...break;
        }
    }
    PG_CATCH();
    {
     ...
        PG_RE_THROW();
    }
    PG_END_TRY();

    MemoryContextSwitchTo(oldContext);

    ActivePortal = saveActivePortal;
    CurrentResourceOwner = saveResourceOwner;
    PortalContext = savePortalContext;

    portal->status = PORTAL_READY;
}

我们发送如 select * from tab01; 这样的查询时,得到的Strategy是: PORTAL_ONE_SELECT

在得知Strategy 为  PORTAL_ONE_SELECT 之后,作了哪些事情呢:

 1 case PORTAL_ONE_SELECT:
 2                 /* Must set snapshot before starting executor. */
 3                 if (use_active_snapshot)
 4                     PushActiveSnapshot(GetActiveSnapshot());
 5                 else
 6                     PushActiveSnapshot(GetTransactionSnapshot());
 7 
 8                 /*
 9                  * Create QueryDesc in portal's context; for the moment, set
10                  * the destination to DestNone.
11                  */
12                 queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts),
13                                             portal->sourceText,
14                                             GetActiveSnapshot(),
15                                             InvalidSnapshot,
16                                             None_Receiver,
17                                             params,
18                                             0);
19 
20                 /*
21                  * If it's a scrollable cursor, executor needs to support
22                  * REWIND and backwards scan, as well as whatever the caller
23                  * might've asked for.
24                  */
25                 if (portal->cursorOptions & CURSOR_OPT_SCROLL)
26                     myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
27                 else
28                     myeflags = eflags;
29 
30                 /*
31                  * Call ExecutorStart to prepare the plan for execution
32                  */
33                 ExecutorStart(queryDesc, myeflags);
34 
35                 /*
36                  * This tells PortalCleanup to shut down the executor
37                  */
38                 portal->queryDesc = queryDesc;
39 
40                 /*
41                  * Remember tuple descriptor (computed by ExecutorStart)
42                  */
43                 portal->tupDesc = queryDesc->tupDesc;
44 
45                 /*
46                  * Reset cursor position data to "start of query"
47                  */
48                 portal->atStart = true;
49                 portal->atEnd = false;    /* allow fetches */
50                 portal->portalPos = 0;
51                 portal->posOverflow = false;
52 
53                 PopActiveSnapshot();
54                 break;

对于 select * from tab01; 这样的查询, myeflags 为0。这里很重要的,就是执行了 ExecutorStart。

这样,为执行做好了准备。

posted @ 2013-05-22 13:26  健哥的数据花园  阅读(653)  评论(0编辑  收藏  举报