@@ -40,6 +40,8 @@ typedef struct vacuumingOptions
4040 bool and_analyze ;
4141 bool full ;
4242 bool freeze ;
43+ bool disable_page_skipping ;
44+ bool skip_locked ;
4345} vacuumingOptions ;
4446
4547
@@ -110,6 +112,8 @@ main(int argc, char *argv[])
110112 {"jobs" , required_argument , NULL , 'j' },
111113 {"maintenance-db" , required_argument , NULL , 2 },
112114 {"analyze-in-stages" , no_argument , NULL , 3 },
115+ {"disable-page-skipping" , no_argument , NULL , 4 },
116+ {"skip-locked" , no_argument , NULL , 5 },
113117 {NULL , 0 , NULL , 0 }
114118 };
115119
@@ -213,6 +217,12 @@ main(int argc, char *argv[])
213217 case 3 :
214218 analyze_in_stages = vacopts .analyze_only = true;
215219 break ;
220+ case 4 :
221+ vacopts .disable_page_skipping = true;
222+ break ;
223+ case 5 :
224+ vacopts .skip_locked = true;
225+ break ;
216226 default :
217227 fprintf (stderr , _ ("Try \"%s --help\" for more information.\n" ), progname );
218228 exit (1 );
@@ -251,6 +261,12 @@ main(int argc, char *argv[])
251261 progname , "freeze" );
252262 exit (1 );
253263 }
264+ if (vacopts .disable_page_skipping )
265+ {
266+ fprintf (stderr , _ ("%s: cannot use the \"%s\" option when performing only analyze\n" ),
267+ progname , "disable-page-skipping" );
268+ exit (1 );
269+ }
254270 /* allow 'and_analyze' with 'analyze_only' */
255271 }
256272
@@ -367,6 +383,22 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
367383 conn = connectDatabase (dbname , host , port , username , prompt_password ,
368384 progname , echo , false, true);
369385
386+ if (vacopts -> disable_page_skipping && PQserverVersion (conn ) < 90600 )
387+ {
388+ PQfinish (conn );
389+ fprintf (stderr , _ ("%s: cannot use the \"%s\" option on server versions older than PostgreSQL 9.6\n" ),
390+ progname , "disable-page-skipping" );
391+ exit (1 );
392+ }
393+
394+ if (vacopts -> skip_locked && PQserverVersion (conn ) < 120000 )
395+ {
396+ PQfinish (conn );
397+ fprintf (stderr , _ ("%s: cannot use the \"%s\" option on server versions older than PostgreSQL 12\n" ),
398+ progname , "skip-locked" );
399+ exit (1 );
400+ }
401+
370402 if (!quiet )
371403 {
372404 if (stage != ANALYZE_NO_STAGE )
@@ -630,23 +662,61 @@ prepare_vacuum_command(PQExpBuffer sql, PGconn *conn,
630662 bool table_pre_qualified ,
631663 const char * progname , bool echo )
632664{
665+ const char * paren = " (" ;
666+ const char * comma = ", " ;
667+ const char * sep = paren ;
668+
633669 resetPQExpBuffer (sql );
634670
635671 if (vacopts -> analyze_only )
636672 {
637673 appendPQExpBufferStr (sql , "ANALYZE" );
638- if (vacopts -> verbose )
639- appendPQExpBufferStr (sql , " VERBOSE" );
674+
675+ /* parenthesized grammar of ANALYZE is supported since v11 */
676+ if (PQserverVersion (conn ) >= 110000 )
677+ {
678+ if (vacopts -> skip_locked )
679+ {
680+ /* SKIP_LOCKED is supported since v12 */
681+ Assert (PQserverVersion (conn ) >= 120000 );
682+ appendPQExpBuffer (sql , "%sSKIP_LOCKED" , sep );
683+ sep = comma ;
684+ }
685+ if (vacopts -> verbose )
686+ {
687+ appendPQExpBuffer (sql , "%sVERBOSE" , sep );
688+ sep = comma ;
689+ }
690+ if (sep != paren )
691+ appendPQExpBufferChar (sql , ')' );
692+ }
693+ else
694+ {
695+ if (vacopts -> verbose )
696+ appendPQExpBufferStr (sql , " VERBOSE" );
697+ }
640698 }
641699 else
642700 {
643701 appendPQExpBufferStr (sql , "VACUUM" );
702+
703+ /* parenthesized grammar of VACUUM is supported since v9.0 */
644704 if (PQserverVersion (conn ) >= 90000 )
645705 {
646- const char * paren = " (" ;
647- const char * comma = ", " ;
648- const char * sep = paren ;
649-
706+ if (vacopts -> disable_page_skipping )
707+ {
708+ /* DISABLE_PAGE_SKIPPING is supported since v9.6 */
709+ Assert (PQserverVersion (conn ) >= 90600 );
710+ appendPQExpBuffer (sql , "%sDISABLE_PAGE_SKIPPING" , sep );
711+ sep = comma ;
712+ }
713+ if (vacopts -> skip_locked )
714+ {
715+ /* SKIP_LOCKED is supported since v12 */
716+ Assert (PQserverVersion (conn ) >= 120000 );
717+ appendPQExpBuffer (sql , "%sSKIP_LOCKED" , sep );
718+ sep = comma ;
719+ }
650720 if (vacopts -> full )
651721 {
652722 appendPQExpBuffer (sql , "%sFULL" , sep );
@@ -1000,11 +1070,13 @@ help(const char *progname)
10001070 printf (_ ("\nOptions:\n" ));
10011071 printf (_ (" -a, --all vacuum all databases\n" ));
10021072 printf (_ (" -d, --dbname=DBNAME database to vacuum\n" ));
1073+ printf (_ (" --disable-page-skipping disable all page-skipping behavior\n" ));
10031074 printf (_ (" -e, --echo show the commands being sent to the server\n" ));
10041075 printf (_ (" -f, --full do full vacuuming\n" ));
10051076 printf (_ (" -F, --freeze freeze row transaction information\n" ));
10061077 printf (_ (" -j, --jobs=NUM use this many concurrent connections to vacuum\n" ));
10071078 printf (_ (" -q, --quiet don't write any messages\n" ));
1079+ printf (_ (" --skip-locked skip relations that cannot be immediately locked\n" ));
10081080 printf (_ (" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" ));
10091081 printf (_ (" -v, --verbose write a lot of output\n" ));
10101082 printf (_ (" -V, --version output version information, then exit\n" ));
0 commit comments