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。
这样,为执行做好了准备。