在定义了Portal之后,需要运行:PortalStart,它主要的任务是明确执行策略,然后再执行 ExecutorStart:
代码太长,进行缩略:
voidPortalStart(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, set10 * 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 support22 * REWIND and backwards scan, as well as whatever the caller23 * might've asked for.24 */25 if (portal->cursorOptions & CURSOR_OPT_SCROLL)26 myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;27 else28 myeflags = eflags;29 30 /*31 * Call ExecutorStart to prepare the plan for execution32 */33 ExecutorStart(queryDesc, myeflags);34 35 /*36 * This tells PortalCleanup to shut down the executor37 */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。
这样,为执行做好了准备。