@@ -2041,8 +2041,11 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
2041
2041
*
2042
2042
* In the first two cases, we can just push the snap onto the stack once
2043
2043
* 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.
2044
2047
*/
2045
- if (snapshot != InvalidSnapshot )
2048
+ if (snapshot != InvalidSnapshot && ! plan -> no_snapshots )
2046
2049
{
2047
2050
if (read_only )
2048
2051
{
@@ -2121,7 +2124,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
2121
2124
* In the default non-read-only case, get a new snapshot, replacing
2122
2125
* any that we pushed in a previous cycle.
2123
2126
*/
2124
- if (snapshot == InvalidSnapshot && !read_only )
2127
+ if (snapshot == InvalidSnapshot && !read_only && ! plan -> no_snapshots )
2125
2128
{
2126
2129
if (pushed_active_snap )
2127
2130
PopActiveSnapshot ();
@@ -2172,7 +2175,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
2172
2175
* If not read-only mode, advance the command counter before each
2173
2176
* command and update the snapshot.
2174
2177
*/
2175
- if (!read_only )
2178
+ if (!read_only && ! plan -> no_snapshots )
2176
2179
{
2177
2180
CommandCounterIncrement ();
2178
2181
UpdateActiveSnapshotCommandId ();
@@ -2203,10 +2206,23 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
2203
2206
else
2204
2207
{
2205
2208
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 ;
2206
2222
2207
2223
ProcessUtility (stmt ,
2208
2224
plansource -> query_string ,
2209
- PROCESS_UTILITY_QUERY ,
2225
+ context ,
2210
2226
paramLI ,
2211
2227
_SPI_current -> queryEnv ,
2212
2228
dest ,
@@ -2638,11 +2654,8 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
2638
2654
oldcxt = MemoryContextSwitchTo (plancxt );
2639
2655
2640
2656
/* 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 ));
2642
2658
newplan -> magic = _SPI_PLAN_MAGIC ;
2643
- newplan -> saved = false;
2644
- newplan -> oneshot = false;
2645
- newplan -> plancache_list = NIL ;
2646
2659
newplan -> plancxt = plancxt ;
2647
2660
newplan -> cursor_options = plan -> cursor_options ;
2648
2661
newplan -> nargs = plan -> nargs ;
@@ -2705,11 +2718,8 @@ _SPI_save_plan(SPIPlanPtr plan)
2705
2718
oldcxt = MemoryContextSwitchTo (plancxt );
2706
2719
2707
2720
/* Copy the SPI plan into its own context */
2708
- newplan = (SPIPlanPtr ) palloc (sizeof (_SPI_plan ));
2721
+ newplan = (SPIPlanPtr ) palloc0 (sizeof (_SPI_plan ));
2709
2722
newplan -> magic = _SPI_PLAN_MAGIC ;
2710
- newplan -> saved = false;
2711
- newplan -> oneshot = false;
2712
- newplan -> plancache_list = NIL ;
2713
2723
newplan -> plancxt = plancxt ;
2714
2724
newplan -> cursor_options = plan -> cursor_options ;
2715
2725
newplan -> nargs = plan -> nargs ;
0 commit comments