@@ -2041,8 +2041,11 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
20412041 *
20422042 * In the first two cases, we can just push the snap onto the stack once
20432043 * for the whole plan list.
2044+ *
2045+ * But if the plan has no_snapshots set to true, then don't manage
2046+ * snapshots at all. The caller should then take care of that.
20442047 */
2045- if (snapshot != InvalidSnapshot )
2048+ if (snapshot != InvalidSnapshot && ! plan -> no_snapshots )
20462049 {
20472050 if (read_only )
20482051 {
@@ -2121,7 +2124,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
21212124 * In the default non-read-only case, get a new snapshot, replacing
21222125 * any that we pushed in a previous cycle.
21232126 */
2124- if (snapshot == InvalidSnapshot && !read_only )
2127+ if (snapshot == InvalidSnapshot && !read_only && ! plan -> no_snapshots )
21252128 {
21262129 if (pushed_active_snap )
21272130 PopActiveSnapshot ();
@@ -2172,7 +2175,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
21722175 * If not read-only mode, advance the command counter before each
21732176 * command and update the snapshot.
21742177 */
2175- if (!read_only )
2178+ if (!read_only && ! plan -> no_snapshots )
21762179 {
21772180 CommandCounterIncrement ();
21782181 UpdateActiveSnapshotCommandId ();
@@ -2203,10 +2206,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
22032206 else
22042207 {
22052208 char completionTag [COMPLETION_TAG_BUFSIZE ];
2209+ ProcessUtilityContext context ;
2210+
2211+ /*
2212+ * If the SPI context is atomic, or we are asked to manage
2213+ * snapshots, then we are in an atomic execution context.
2214+ * Conversely, to propagate a nonatomic execution context, the
2215+ * caller must be in a nonatomic SPI context and manage
2216+ * snapshots itself.
2217+ */
2218+ if (_SPI_current -> atomic || !plan -> no_snapshots )
2219+ context = PROCESS_UTILITY_QUERY ;
2220+ else
2221+ context = PROCESS_UTILITY_QUERY_NONATOMIC ;
22062222
22072223 ProcessUtility (stmt ,
22082224 plansource -> query_string ,
2209- PROCESS_UTILITY_QUERY ,
2225+ context ,
22102226 paramLI ,
22112227 _SPI_current -> queryEnv ,
22122228 dest ,
@@ -2638,11 +2654,8 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
26382654 oldcxt = MemoryContextSwitchTo (plancxt );
26392655
26402656 /* Copy the SPI_plan struct and subsidiary data into the new context */
2641- newplan = (SPIPlanPtr ) palloc (sizeof (_SPI_plan ));
2657+ newplan = (SPIPlanPtr ) palloc0 (sizeof (_SPI_plan ));
26422658 newplan -> magic = _SPI_PLAN_MAGIC ;
2643- newplan -> saved = false;
2644- newplan -> oneshot = false;
2645- newplan -> plancache_list = NIL ;
26462659 newplan -> plancxt = plancxt ;
26472660 newplan -> cursor_options = plan -> cursor_options ;
26482661 newplan -> nargs = plan -> nargs ;
@@ -2705,11 +2718,8 @@ _SPI_save_plan(SPIPlanPtr plan)
27052718 oldcxt = MemoryContextSwitchTo (plancxt );
27062719
27072720 /* Copy the SPI plan into its own context */
2708- newplan = (SPIPlanPtr ) palloc (sizeof (_SPI_plan ));
2721+ newplan = (SPIPlanPtr ) palloc0 (sizeof (_SPI_plan ));
27092722 newplan -> magic = _SPI_PLAN_MAGIC ;
2710- newplan -> saved = false;
2711- newplan -> oneshot = false;
2712- newplan -> plancache_list = NIL ;
27132723 newplan -> plancxt = plancxt ;
27142724 newplan -> cursor_options = plan -> cursor_options ;
27152725 newplan -> nargs = plan -> nargs ;
0 commit comments