* PortalRunUtility * Execute a utility statement inside a portal. */
| 1335 | * Execute a utility statement inside a portal. |
| 1336 | */ |
| 1337 | static void |
| 1338 | PortalRunUtility(Portal portal, PlannedStmt *pstmt, |
| 1339 | bool isTopLevel, bool setHoldSnapshot, |
| 1340 | DestReceiver *dest, QueryCompletion *qc) |
| 1341 | { |
| 1342 | Node *utilityStmt = pstmt->utilityStmt; |
| 1343 | /* |
| 1344 | * Set snapshot if utility stmt needs one. |
| 1345 | */ |
| 1346 | if (PlannedStmtRequiresSnapshot(pstmt)) |
| 1347 | { |
| 1348 | Snapshot snapshot = GetTransactionSnapshot(); |
| 1349 | |
| 1350 | /* If told to, register the snapshot we're using and save in portal */ |
| 1351 | if (setHoldSnapshot) |
| 1352 | { |
| 1353 | snapshot = RegisterSnapshot(snapshot); |
| 1354 | portal->holdSnapshot = snapshot; |
| 1355 | } |
| 1356 | |
| 1357 | /* |
| 1358 | * In any case, make the snapshot active and remember it in portal. |
| 1359 | * Because the portal now references the snapshot, we must tell |
| 1360 | * snapmgr.c that the snapshot belongs to the portal's transaction |
| 1361 | * level, else we risk portalSnapshot becoming a dangling pointer. |
| 1362 | */ |
| 1363 | PushActiveSnapshotWithLevel(snapshot, portal->createLevel); |
| 1364 | /* PushActiveSnapshotWithLevel might have copied the snapshot */ |
| 1365 | portal->portalSnapshot = GetActiveSnapshot(); |
| 1366 | } |
| 1367 | else |
| 1368 | portal->portalSnapshot = NULL; |
| 1369 | |
| 1370 | /* check if this utility statement need to be involved into resource queue |
| 1371 | * mgmt */ |
| 1372 | ResHandleUtilityStmt(portal, utilityStmt); |
| 1373 | |
| 1374 | ProcessUtility(pstmt, |
| 1375 | portal->sourceText ? portal->sourceText : "(Source text for portal is not available)", |
| 1376 | (portal->cplan != NULL), /* protect tree if in plancache */ |
| 1377 | isTopLevel ? PROCESS_UTILITY_TOPLEVEL : PROCESS_UTILITY_QUERY, |
| 1378 | portal->portalParams, |
| 1379 | portal->queryEnv, |
| 1380 | dest, |
| 1381 | qc); |
| 1382 | |
| 1383 | /* Some utility statements may change context on us */ |
| 1384 | MemoryContextSwitchTo(portal->portalContext); |
| 1385 | |
| 1386 | /* |
| 1387 | * Some utility commands (e.g., VACUUM) pop the ActiveSnapshot stack from |
| 1388 | * under us, so don't complain if it's now empty. Otherwise, our snapshot |
| 1389 | * should be the top one; pop it. Note that this could be a different |
| 1390 | * snapshot from the one we made above; see EnsurePortalSnapshotExists. |
| 1391 | */ |
| 1392 | if (portal->portalSnapshot != NULL && ActiveSnapshotSet()) |
| 1393 | { |
| 1394 | Assert(portal->portalSnapshot == GetActiveSnapshot()); |
no test coverage detected