105105ExecVacuum (ParseState * pstate , VacuumStmt * vacstmt , bool isTopLevel )
106106{
107107 VacuumParams params ;
108+ BufferAccessStrategy bstrategy = NULL ;
108109 bool verbose = false;
109110 bool skip_locked = false;
110111 bool analyze = false;
@@ -115,6 +116,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
115116 bool process_toast = true;
116117 bool skip_database_stats = false;
117118 bool only_database_stats = false;
119+ MemoryContext vac_context ;
118120 ListCell * lc ;
119121
120122 /* index_cleanup and truncate values unspecified for now */
@@ -254,6 +256,42 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
254256 }
255257 }
256258
259+
260+ /*
261+ * Sanity check DISABLE_PAGE_SKIPPING option.
262+ */
263+ if ((params .options & VACOPT_FULL ) != 0 &&
264+ (params .options & VACOPT_DISABLE_PAGE_SKIPPING ) != 0 )
265+ ereport (ERROR ,
266+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
267+ errmsg ("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL" )));
268+
269+ /* sanity check for PROCESS_TOAST */
270+ if ((params .options & VACOPT_FULL ) != 0 &&
271+ (params .options & VACOPT_PROCESS_TOAST ) == 0 )
272+ ereport (ERROR ,
273+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
274+ errmsg ("PROCESS_TOAST required with VACUUM FULL" )));
275+
276+ /* sanity check for ONLY_DATABASE_STATS */
277+ if (params .options & VACOPT_ONLY_DATABASE_STATS )
278+ {
279+ Assert (params .options & VACOPT_VACUUM );
280+ if (vacstmt -> rels != NIL )
281+ ereport (ERROR ,
282+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
283+ errmsg ("ONLY_DATABASE_STATS cannot be specified with a list of tables" )));
284+ /* don't require people to turn off PROCESS_TOAST/MAIN explicitly */
285+ if (params .options & ~(VACOPT_VACUUM |
286+ VACOPT_VERBOSE |
287+ VACOPT_PROCESS_MAIN |
288+ VACOPT_PROCESS_TOAST |
289+ VACOPT_ONLY_DATABASE_STATS ))
290+ ereport (ERROR ,
291+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
292+ errmsg ("ONLY_DATABASE_STATS cannot be specified with other VACUUM options" )));
293+ }
294+
257295 /*
258296 * All freeze ages are zero if the FREEZE option is given; otherwise pass
259297 * them as -1 which means to use the default values.
@@ -279,12 +317,43 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
279317 /* user-invoked vacuum uses VACOPT_VERBOSE instead of log_min_duration */
280318 params .log_min_duration = -1 ;
281319
320+ /*
321+ * Create special memory context for cross-transaction storage.
322+ *
323+ * Since it is a child of PortalContext, it will go away eventually even
324+ * if we suffer an error; there's no need for special abort cleanup logic.
325+ */
326+ vac_context = AllocSetContextCreate (PortalContext ,
327+ "Vacuum" ,
328+ ALLOCSET_DEFAULT_SIZES );
329+
330+ /*
331+ * Make a buffer strategy object in the cross-transaction memory context.
332+ * We needn't bother making this for VACUUM (FULL) or VACUUM
333+ * (ONLY_DATABASE_STATS) as they'll not make use of it. VACUUM (FULL,
334+ * ANALYZE) is possible, so we'd better ensure that we make a strategy
335+ * when we see ANALYZE.
336+ */
337+ if ((params .options & (VACOPT_ONLY_DATABASE_STATS |
338+ VACOPT_FULL )) == 0 ||
339+ (params .options & VACOPT_ANALYZE ) != 0 )
340+ {
341+
342+ MemoryContext old_context = MemoryContextSwitchTo (vac_context );
343+
344+ bstrategy = GetAccessStrategy (BAS_VACUUM );
345+ MemoryContextSwitchTo (old_context );
346+ }
347+
282348 /* Now go through the common routine */
283- vacuum (vacstmt -> rels , & params , NULL , isTopLevel );
349+ vacuum (vacstmt -> rels , & params , bstrategy , vac_context , isTopLevel );
350+
351+ /* Finally, clean up the vacuum memory context */
352+ MemoryContextDelete (vac_context );
284353}
285354
286355/*
287- * Internal entry point for VACUUM and ANALYZE commands.
356+ * Internal entry point for autovacuum and the VACUUM / ANALYZE commands.
288357 *
289358 * relations, if not NIL, is a list of VacuumRelation to process; otherwise,
290359 * we process all relevant tables in the database. For each VacuumRelation,
@@ -294,21 +363,23 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
294363 * params contains a set of parameters that can be used to customize the
295364 * behavior.
296365 *
297- * bstrategy is normally given as NULL, but in autovacuum it can be passed
298- * in to use the same buffer strategy object across multiple vacuum() calls.
366+ * bstrategy may be passed in as NULL when the caller does not want to
367+ * restrict the number of shared_buffers that VACUUM / ANALYZE can use,
368+ * otherwise, the caller must build a BufferAccessStrategy with the number of
369+ * shared_buffers that VACUUM / ANALYZE should try to limit themselves to
370+ * using.
299371 *
300372 * isTopLevel should be passed down from ProcessUtility.
301373 *
302374 * It is the caller's responsibility that all parameters are allocated in a
303375 * memory context that will not disappear at transaction commit.
304376 */
305377void
306- vacuum (List * relations , VacuumParams * params ,
307- BufferAccessStrategy bstrategy , bool isTopLevel )
378+ vacuum (List * relations , VacuumParams * params , BufferAccessStrategy bstrategy ,
379+ MemoryContext vac_context , bool isTopLevel )
308380{
309381 static bool in_vacuum = false;
310382
311- MemoryContext vac_context ;
312383 const char * stmttype ;
313384 volatile bool in_outer_xact ,
314385 use_own_xacts ;
@@ -344,69 +415,6 @@ vacuum(List *relations, VacuumParams *params,
344415 errmsg ("%s cannot be executed from VACUUM or ANALYZE" ,
345416 stmttype )));
346417
347- /*
348- * Sanity check DISABLE_PAGE_SKIPPING option.
349- */
350- if ((params -> options & VACOPT_FULL ) != 0 &&
351- (params -> options & VACOPT_DISABLE_PAGE_SKIPPING ) != 0 )
352- ereport (ERROR ,
353- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
354- errmsg ("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL" )));
355-
356- /* sanity check for PROCESS_TOAST */
357- if ((params -> options & VACOPT_FULL ) != 0 &&
358- (params -> options & VACOPT_PROCESS_TOAST ) == 0 )
359- ereport (ERROR ,
360- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
361- errmsg ("PROCESS_TOAST required with VACUUM FULL" )));
362-
363- /* sanity check for ONLY_DATABASE_STATS */
364- if (params -> options & VACOPT_ONLY_DATABASE_STATS )
365- {
366- Assert (params -> options & VACOPT_VACUUM );
367- if (relations != NIL )
368- ereport (ERROR ,
369- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
370- errmsg ("ONLY_DATABASE_STATS cannot be specified with a list of tables" )));
371- /* don't require people to turn off PROCESS_TOAST/MAIN explicitly */
372- if (params -> options & ~(VACOPT_VACUUM |
373- VACOPT_VERBOSE |
374- VACOPT_PROCESS_MAIN |
375- VACOPT_PROCESS_TOAST |
376- VACOPT_ONLY_DATABASE_STATS ))
377- ereport (ERROR ,
378- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
379- errmsg ("ONLY_DATABASE_STATS cannot be specified with other VACUUM options" )));
380- }
381-
382- /*
383- * Create special memory context for cross-transaction storage.
384- *
385- * Since it is a child of PortalContext, it will go away eventually even
386- * if we suffer an error; there's no need for special abort cleanup logic.
387- */
388- vac_context = AllocSetContextCreate (PortalContext ,
389- "Vacuum" ,
390- ALLOCSET_DEFAULT_SIZES );
391-
392- /*
393- * If caller didn't give us a buffer strategy object, make one in the
394- * cross-transaction memory context. We needn't bother making this for
395- * VACUUM (FULL) or VACUUM (ONLY_DATABASE_STATS) as they'll not make use
396- * of it. VACUUM (FULL, ANALYZE) is possible, so we'd better ensure that
397- * we make a strategy when we see ANALYZE.
398- */
399- if (bstrategy == NULL &&
400- ((params -> options & (VACOPT_ONLY_DATABASE_STATS |
401- VACOPT_FULL )) == 0 ||
402- (params -> options & VACOPT_ANALYZE ) != 0 ))
403- {
404- MemoryContext old_context = MemoryContextSwitchTo (vac_context );
405-
406- bstrategy = GetAccessStrategy (BAS_VACUUM );
407- MemoryContextSwitchTo (old_context );
408- }
409-
410418 /*
411419 * Build list of relation(s) to process, putting any new data in
412420 * vac_context for safekeeping.
@@ -578,12 +586,6 @@ vacuum(List *relations, VacuumParams *params,
578586 vac_update_datfrozenxid ();
579587 }
580588
581- /*
582- * Clean up working storage --- note we must do this after
583- * StartTransactionCommand, else we might be trying to delete the active
584- * context!
585- */
586- MemoryContextDelete (vac_context );
587589}
588590
589591/*
0 commit comments