105
105
ExecVacuum (ParseState * pstate , VacuumStmt * vacstmt , bool isTopLevel )
106
106
{
107
107
VacuumParams params ;
108
+ BufferAccessStrategy bstrategy = NULL ;
108
109
bool verbose = false;
109
110
bool skip_locked = false;
110
111
bool analyze = false;
@@ -115,6 +116,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
115
116
bool process_toast = true;
116
117
bool skip_database_stats = false;
117
118
bool only_database_stats = false;
119
+ MemoryContext vac_context ;
118
120
ListCell * lc ;
119
121
120
122
/* index_cleanup and truncate values unspecified for now */
@@ -254,6 +256,42 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
254
256
}
255
257
}
256
258
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
+
257
295
/*
258
296
* All freeze ages are zero if the FREEZE option is given; otherwise pass
259
297
* them as -1 which means to use the default values.
@@ -279,12 +317,43 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
279
317
/* user-invoked vacuum uses VACOPT_VERBOSE instead of log_min_duration */
280
318
params .log_min_duration = -1 ;
281
319
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
+
282
348
/* 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 );
284
353
}
285
354
286
355
/*
287
- * Internal entry point for VACUUM and ANALYZE commands.
356
+ * Internal entry point for autovacuum and the VACUUM / ANALYZE commands.
288
357
*
289
358
* relations, if not NIL, is a list of VacuumRelation to process; otherwise,
290
359
* we process all relevant tables in the database. For each VacuumRelation,
@@ -294,21 +363,23 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
294
363
* params contains a set of parameters that can be used to customize the
295
364
* behavior.
296
365
*
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.
299
371
*
300
372
* isTopLevel should be passed down from ProcessUtility.
301
373
*
302
374
* It is the caller's responsibility that all parameters are allocated in a
303
375
* memory context that will not disappear at transaction commit.
304
376
*/
305
377
void
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 )
308
380
{
309
381
static bool in_vacuum = false;
310
382
311
- MemoryContext vac_context ;
312
383
const char * stmttype ;
313
384
volatile bool in_outer_xact ,
314
385
use_own_xacts ;
@@ -344,69 +415,6 @@ vacuum(List *relations, VacuumParams *params,
344
415
errmsg ("%s cannot be executed from VACUUM or ANALYZE" ,
345
416
stmttype )));
346
417
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
-
410
418
/*
411
419
* Build list of relation(s) to process, putting any new data in
412
420
* vac_context for safekeeping.
@@ -578,12 +586,6 @@ vacuum(List *relations, VacuumParams *params,
578
586
vac_update_datfrozenxid ();
579
587
}
580
588
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 );
587
589
}
588
590
589
591
/*
0 commit comments