diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml
new file mode 100644
index 097ea91..f1cbdc8
*** a/doc/src/sgml/ref/clusterdb.sgml
--- b/doc/src/sgml/ref/clusterdb.sgml
*************** PostgreSQL documentation
*** 24,30 ****
     <command>clusterdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
     <group choice="opt"><arg choice="plain"><option>--verbose</option></arg><arg choice="plain"><option>-v</option></arg></group>
!    <arg choice="opt"><group choice="plain"><arg choice="plain"><option>--table</option></arg><arg choice="plain"><option>-t</option></arg></group> <replaceable>table</replaceable> </arg>
     <arg choice="opt"><replaceable>dbname</replaceable></arg>
    </cmdsynopsis>
  
--- 24,35 ----
     <command>clusterdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
     <group choice="opt"><arg choice="plain"><option>--verbose</option></arg><arg choice="plain"><option>-v</option></arg></group>
!    <arg choice="opt" rep="repeat">
!      <group choice="plain">
!        <arg choice="plain"><option>--table</option></arg>
!        <arg choice="plain"><option>-t</option></arg>
!      </group>
!      <replaceable>table</replaceable> </arg>
     <arg choice="opt"><replaceable>dbname</replaceable></arg>
    </cmdsynopsis>
  
*************** PostgreSQL documentation
*** 117,122 ****
--- 122,129 ----
        <listitem>
         <para>
          Cluster <replaceable class="parameter">table</replaceable> only.
+         Multiple tables can be clustered by writing multiple
+         <option>-t</> switches.
         </para>
        </listitem>
       </varlistentry>
diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml
new file mode 100644
index f4668e7..0d73294
*** a/doc/src/sgml/ref/pg_restore.sgml
--- b/doc/src/sgml/ref/pg_restore.sgml
***************
*** 400,406 ****
        <term><option>--table=<replaceable class="parameter">table</replaceable></option></term>
        <listitem>
         <para>
!         Restore definition and/or data of named table only.  This can be
          combined with the <option>-n</option> option to specify a schema.
         </para>
        </listitem>
--- 400,407 ----
        <term><option>--table=<replaceable class="parameter">table</replaceable></option></term>
        <listitem>
         <para>
!         Restore definition and/or data of named table only. Multiple tables
!         may be specified with multiple <option>-t</> switches. This can be
          combined with the <option>-n</option> option to specify a schema.
         </para>
        </listitem>
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
new file mode 100644
index 781012f..47907c7
*** a/doc/src/sgml/ref/reindexdb.sgml
--- b/doc/src/sgml/ref/reindexdb.sgml
*************** PostgreSQL documentation
*** 23,42 ****
    <cmdsynopsis>
     <command>reindexdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
!    <group choice="opt">
      <group choice="plain">
       <arg choice="plain"><option>--table</option></arg>
       <arg choice="plain"><option>-t</option></arg>
      </group>
      <replaceable>table</replaceable>
!    </group>
!    <group choice="opt">
      <group choice="plain">
       <arg choice="plain"><option>--index</option></arg>
       <arg choice="plain"><option>-i</option></arg>
      </group>
      <replaceable>index</replaceable>
!    </group>
     <arg choice="opt"><replaceable>dbname</replaceable></arg>
    </cmdsynopsis>
  
--- 23,43 ----
    <cmdsynopsis>
     <command>reindexdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
!    <arg choice="opt" rep="repeat">
      <group choice="plain">
       <arg choice="plain"><option>--table</option></arg>
       <arg choice="plain"><option>-t</option></arg>
      </group>
      <replaceable>table</replaceable>
!    </arg>
!    <arg choice="opt" rep="repeat">
      <group choice="plain">
       <arg choice="plain"><option>--index</option></arg>
       <arg choice="plain"><option>-i</option></arg>
      </group>
      <replaceable>index</replaceable>
!    </arg>
! 
     <arg choice="opt"><replaceable>dbname</replaceable></arg>
    </cmdsynopsis>
  
*************** PostgreSQL documentation
*** 128,133 ****
--- 129,136 ----
        <listitem>
         <para>
          Recreate <replaceable class="parameter">index</replaceable> only.
+         Multiple indexes can be recreated by writing multiple
+         <option>-i</> switches.
         </para>
        </listitem>
       </varlistentry>
*************** PostgreSQL documentation
*** 158,163 ****
--- 161,168 ----
        <listitem>
         <para>
          Reindex <replaceable class="parameter">table</replaceable> only.
+         Multiple tables can be reindexed by writing multiple
+         <option>-t</> switches.
         </para>
        </listitem>
       </varlistentry>
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
new file mode 100644
index c60ba44..13dfe57
*** a/doc/src/sgml/ref/vacuumdb.sgml
--- b/doc/src/sgml/ref/vacuumdb.sgml
*************** PostgreSQL documentation
*** 24,30 ****
     <command>vacuumdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
     <arg rep="repeat"><replaceable>option</replaceable></arg>
!    <arg choice="opt">
      <group choice="plain">
       <arg choice="plain"><option>--table</option></arg>
       <arg choice="plain"><option>-t</option></arg>
--- 24,30 ----
     <command>vacuumdb</command>
     <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
     <arg rep="repeat"><replaceable>option</replaceable></arg>
!    <arg choice="opt" rep="repeat">
      <group choice="plain">
       <arg choice="plain"><option>--table</option></arg>
       <arg choice="plain"><option>-t</option></arg>
*************** PostgreSQL documentation
*** 147,152 ****
--- 147,154 ----
          Clean or analyze <replaceable class="parameter">table</replaceable> only.
          Column names can be specified only in conjunction with
          the <option>--analyze</option> or <option>--analyze-only</option> options.
+         Multiple tables can be vacuumed by writing multiple
+         <option>-t</> switches.
         </para>
         <tip>
          <para>
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
new file mode 100644
index 611c8e3..88c07be
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
*************** simple_oid_list_append(SimpleOidList *li
*** 898,921 ****
  	list->tail = cell;
  }
  
- void
- simple_string_list_append(SimpleStringList *list, const char *val)
- {
- 	SimpleStringListCell *cell;
- 
- 	/* this calculation correctly accounts for the null trailing byte */
- 	cell = (SimpleStringListCell *)
- 		pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
- 	cell->next = NULL;
- 	strcpy(cell->val, val);
- 
- 	if (list->tail)
- 		list->tail->next = cell;
- 	else
- 		list->head = cell;
- 	list->tail = cell;
- }
- 
  bool
  simple_oid_list_member(SimpleOidList *list, Oid val)
  {
--- 898,903 ----
*************** simple_oid_list_member(SimpleOidList *li
*** 928,943 ****
  	}
  	return false;
  }
- 
- bool
- simple_string_list_member(SimpleStringList *list, const char *val)
- {
- 	SimpleStringListCell *cell;
- 
- 	for (cell = list->head; cell; cell = cell->next)
- 	{
- 		if (strcmp(cell->val, val) == 0)
- 			return true;
- 	}
- 	return false;
- }
--- 910,912 ----
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
new file mode 100644
index 639ee9e..621c510
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
***************
*** 17,23 ****
  #include <ctype.h>
  
  #include "dumputils.h"
! 
  #include "parser/keywords.h"
  
  
--- 17,23 ----
  #include <ctype.h>
  
  #include "dumputils.h"
! #include "dumpmem.h"
  #include "parser/keywords.h"
  
  
*************** exit_nicely(int code)
*** 1352,1354 ****
--- 1352,1386 ----
  
  	exit(code);
  }
+ 
+ void
+ simple_string_list_append(SimpleStringList *list, const char *val)
+ {
+     SimpleStringListCell *cell;
+ 
+     /* this calculation correctly accounts for the null trailing byte */
+     cell = (SimpleStringListCell *)
+         pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
+ 
+     cell->next = NULL;
+     strcpy(cell->val, val);
+ 
+     if (list->tail)
+         list->tail->next = cell;
+     else
+         list->head = cell;
+     list->tail = cell;
+ }
+ 
+ bool
+ simple_string_list_member(SimpleStringList *list, const char *val)
+ {
+     SimpleStringListCell *cell;
+ 
+     for (cell = list->head; cell; cell = cell->next)
+     {
+         if (strcmp(cell->val, val) == 0)
+             return true;
+     }
+     return false;
+ }
diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
new file mode 100644
index 4ef8cb3..a300e7e
*** a/src/bin/pg_dump/dumputils.h
--- b/src/bin/pg_dump/dumputils.h
*************** typedef enum					/* bits returned by set
*** 27,32 ****
--- 27,45 ----
  	DUMP_UNSECTIONED = 0xff
  } DumpSections;
  
+ typedef struct SimpleStringListCell
+ {
+     struct SimpleStringListCell *next;
+     char        val[1];         /* VARIABLE LENGTH FIELD */
+ } SimpleStringListCell;
+ 
+ typedef struct SimpleStringList
+ {
+     SimpleStringListCell *head;
+     SimpleStringListCell *tail;
+ } SimpleStringList;
+ 
+ 
  typedef void (*on_exit_nicely_callback) (int code, void *arg);
  
  extern int	quote_all_identifiers;
*************** __attribute__((format(PG_PRINTF_ATTRIBUT
*** 75,78 ****
--- 88,95 ----
  extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
  extern void exit_nicely(int code) __attribute__((noreturn));
  
+ extern void simple_string_list_append(SimpleStringList *list, const char *val);
+ extern bool simple_string_list_member(SimpleStringList *list, const char *val);
+ 
+ 
  #endif   /* DUMPUTILS_H */
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
new file mode 100644
index 3b49395..9972e68
*** a/src/bin/pg_dump/pg_backup.h
--- b/src/bin/pg_dump/pg_backup.h
***************
*** 26,32 ****
  #include "postgres_fe.h"
  
  #include "pg_dump.h"
! 
  #include "libpq-fe.h"
  
  
--- 26,32 ----
  #include "postgres_fe.h"
  
  #include "pg_dump.h"
! #include "dumputils.h"
  #include "libpq-fe.h"
  
  
*************** typedef struct _restoreOptions
*** 125,133 ****
  	int			selTable;
  	char	   *indexNames;
  	char	   *functionNames;
- 	char	   *tableNames;
  	char	   *schemaNames;
  	char	   *triggerNames;
  
  	int			useDB;
  	char	   *dbname;
--- 125,133 ----
  	int			selTable;
  	char	   *indexNames;
  	char	   *functionNames;
  	char	   *schemaNames;
  	char	   *triggerNames;
+ 	SimpleStringList tableNames;
  
  	int			useDB;
  	char	   *dbname;
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
new file mode 100644
index 1fead28..a810efd
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
*************** _tocEntryRequired(TocEntry *te, teSectio
*** 2493,2499 ****
  		{
  			if (!ropt->selTable)
  				return 0;
! 			if (ropt->tableNames && strcmp(ropt->tableNames, te->tag) != 0)
  				return 0;
  		}
  		else if (strcmp(te->desc, "INDEX") == 0)
--- 2493,2499 ----
  		{
  			if (!ropt->selTable)
  				return 0;
! 			if (ropt->tableNames.head != NULL && (!(simple_string_list_member(&ropt->tableNames, te->tag))))
  				return 0;
  		}
  		else if (strcmp(te->desc, "INDEX") == 0)
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
new file mode 100644
index aa1546a..344f705
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
*************** typedef struct SimpleOidList
*** 58,74 ****
  	SimpleOidListCell *tail;
  } SimpleOidList;
  
- typedef struct SimpleStringListCell
- {
- 	struct SimpleStringListCell *next;
- 	char		val[1];			/* VARIABLE LENGTH FIELD */
- } SimpleStringListCell;
- 
- typedef struct SimpleStringList
- {
- 	SimpleStringListCell *head;
- 	SimpleStringListCell *tail;
- } SimpleStringList;
  
  /*
   * The data structures used to store system catalog information.  Every
--- 58,63 ----
*************** extern CollInfo *findCollationByOid(Oid 
*** 533,541 ****
  extern NamespaceInfo *findNamespaceByOid(Oid oid);
  
  extern void simple_oid_list_append(SimpleOidList *list, Oid val);
- extern void simple_string_list_append(SimpleStringList *list, const char *val);
  extern bool simple_oid_list_member(SimpleOidList *list, Oid val);
- extern bool simple_string_list_member(SimpleStringList *list, const char *val);
  
  extern void parseOidArray(const char *str, Oid *array, int arraysize);
  
--- 522,528 ----
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
new file mode 100644
index 49d799b..45b8b58
*** a/src/bin/pg_dump/pg_restore.c
--- b/src/bin/pg_dump/pg_restore.c
*************** main(int argc, char **argv)
*** 234,240 ****
  			case 't':			/* Dump data for this table only */
  				opts->selTypes = 1;
  				opts->selTable = 1;
! 				opts->tableNames = pg_strdup(optarg);
  				break;
  
  			case 'U':
--- 234,240 ----
  			case 't':			/* Dump data for this table only */
  				opts->selTypes = 1;
  				opts->selTable = 1;
! 				simple_string_list_append(&opts->tableNames, optarg);
  				break;
  
  			case 'U':
*************** usage(const char *progname)
*** 424,430 ****
  	printf(_("  -P, --function=NAME(args)    restore named function\n"));
  	printf(_("  -s, --schema-only            restore only the schema, no data\n"));
  	printf(_("  -S, --superuser=NAME         superuser user name to use for disabling triggers\n"));
! 	printf(_("  -t, --table=NAME             restore named table\n"));
  	printf(_("  -T, --trigger=NAME           restore named trigger\n"));
  	printf(_("  -x, --no-privileges          skip restoration of access privileges (grant/revoke)\n"));
  	printf(_("  -1, --single-transaction     restore as a single transaction\n"));
--- 424,430 ----
  	printf(_("  -P, --function=NAME(args)    restore named function\n"));
  	printf(_("  -s, --schema-only            restore only the schema, no data\n"));
  	printf(_("  -S, --superuser=NAME         superuser user name to use for disabling triggers\n"));
! 	printf(_("  -t, --table=NAME             restore named table(s)\n"));
  	printf(_("  -T, --trigger=NAME           restore named trigger\n"));
  	printf(_("  -x, --no-privileges          skip restoration of access privileges (grant/revoke)\n"));
  	printf(_("  -1, --single-transaction     restore as a single transaction\n"));
diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile
new file mode 100644
index 0980b4c..d9ba29d
*** a/src/bin/scripts/Makefile
--- b/src/bin/scripts/Makefile
*************** dropdb: dropdb.o common.o dumputils.o kw
*** 32,38 ****
  droplang: droplang.o common.o print.o mbprint.o | submake-libpq
  dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
! vacuumdb: vacuumdb.o common.o | submake-libpq
  reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  
  dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
--- 32,38 ----
  droplang: droplang.o common.o print.o mbprint.o | submake-libpq
  dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
! vacuumdb: vacuumdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  
  dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c
new file mode 100644
index 261b438..4f163ee
*** a/src/bin/scripts/clusterdb.c
--- b/src/bin/scripts/clusterdb.c
*************** main(int argc, char *argv[])
*** 58,65 ****
  	bool		echo = false;
  	bool		quiet = false;
  	bool		alldb = false;
- 	char	   *table = NULL;
  	bool		verbose = false;
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
--- 58,65 ----
  	bool		echo = false;
  	bool		quiet = false;
  	bool		alldb = false;
  	bool		verbose = false;
+ 	SimpleStringList tables = {NULL, NULL};
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
*************** main(int argc, char *argv[])
*** 98,104 ****
  				alldb = true;
  				break;
  			case 't':
! 				table = pg_strdup(optarg);
  				break;
  			case 'v':
  				verbose = true;
--- 98,104 ----
  				alldb = true;
  				break;
  			case 't':
! 				simple_string_list_append(&tables, optarg);
  				break;
  			case 'v':
  				verbose = true;
*************** main(int argc, char *argv[])
*** 140,148 ****
  					progname);
  			exit(1);
  		}
! 		if (table)
  		{
! 			fprintf(stderr, _("%s: cannot cluster a specific table in all databases\n"),
  					progname);
  			exit(1);
  		}
--- 140,149 ----
  					progname);
  			exit(1);
  		}
! 
! 		if (tables.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot cluster specific table(s) in all databases\n"),
  					progname);
  			exit(1);
  		}
*************** main(int argc, char *argv[])
*** 162,170 ****
  				dbname = get_user_name(progname);
  		}
  
! 		cluster_one_database(dbname, verbose, table,
! 							 host, port, username, prompt_password,
! 							 progname, echo);
  	}
  
  	exit(0);
--- 163,182 ----
  				dbname = get_user_name(progname);
  		}
  
! 		if (tables.head != NULL)
! 		{
! 			SimpleStringListCell *cell;
! 			for (cell = tables.head; cell; cell = cell->next)
! 			{
! 				cluster_one_database(dbname, verbose, cell->val,
! 									 host, port, username, prompt_password,
! 									 progname, echo);
! 			}
! 		}
! 		else
! 			cluster_one_database(dbname, verbose, NULL,
! 								 host, port, username, prompt_password,
! 								 progname, echo);
  	}
  
  	exit(0);
*************** help(const char *progname)
*** 253,259 ****
  	printf(_("  -d, --dbname=DBNAME       database to cluster\n"));
  	printf(_("  -e, --echo                show the commands being sent to the server\n"));
  	printf(_("  -q, --quiet               don't write any messages\n"));
! 	printf(_("  -t, --table=TABLE         cluster specific table only\n"));
  	printf(_("  -v, --verbose             write a lot of output\n"));
  	printf(_("  -V, --version             output version information, then exit\n"));
  	printf(_("  -?, --help                show this help, then exit\n"));
--- 265,271 ----
  	printf(_("  -d, --dbname=DBNAME       database to cluster\n"));
  	printf(_("  -e, --echo                show the commands being sent to the server\n"));
  	printf(_("  -q, --quiet               don't write any messages\n"));
! 	printf(_("  -t, --table=TABLE         cluster specific table(s) only\n"));
  	printf(_("  -v, --verbose             write a lot of output\n"));
  	printf(_("  -V, --version             output version information, then exit\n"));
  	printf(_("  -?, --help                show this help, then exit\n"));
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
new file mode 100644
index f61dada..6b1ca49
*** a/src/bin/scripts/reindexdb.c
--- b/src/bin/scripts/reindexdb.c
*************** main(int argc, char *argv[])
*** 64,71 ****
  	bool		alldb = false;
  	bool		echo = false;
  	bool		quiet = false;
! 	const char *table = NULL;
! 	const char *index = NULL;
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
--- 64,71 ----
  	bool		alldb = false;
  	bool		echo = false;
  	bool		quiet = false;
! 	SimpleStringList indexes = {NULL, NULL};
! 	SimpleStringList tables = {NULL, NULL};
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
*************** main(int argc, char *argv[])
*** 108,117 ****
  				syscatalog = true;
  				break;
  			case 't':
! 				table = pg_strdup(optarg);
  				break;
  			case 'i':
! 				index = pg_strdup(optarg);
  				break;
  			case 2:
  				maintenance_db = pg_strdup(optarg);
--- 108,117 ----
  				syscatalog = true;
  				break;
  			case 't':
! 				simple_string_list_append(&tables, optarg);
  				break;
  			case 'i':
! 				simple_string_list_append(&indexes, optarg);
  				break;
  			case 2:
  				maintenance_db = pg_strdup(optarg);
*************** main(int argc, char *argv[])
*** 154,167 ****
  			fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
! 		if (table)
  		{
! 			fprintf(stderr, _("%s: cannot reindex a specific table in all databases\n"), progname);
  			exit(1);
  		}
! 		if (index)
  		{
! 			fprintf(stderr, _("%s: cannot reindex a specific index in all databases\n"), progname);
  			exit(1);
  		}
  
--- 154,167 ----
  			fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
! 		if (tables.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
  			exit(1);
  		}
! 		if (indexes.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot reindex specific index(es) in all databases\n"), progname);
  			exit(1);
  		}
  
*************** main(int argc, char *argv[])
*** 170,183 ****
  	}
  	else if (syscatalog)
  	{
! 		if (table)
  		{
! 			fprintf(stderr, _("%s: cannot reindex a specific table and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
! 		if (index)
  		{
! 			fprintf(stderr, _("%s: cannot reindex a specific index and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
  
--- 170,183 ----
  	}
  	else if (syscatalog)
  	{
! 		if (tables.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
! 		if (indexes.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot reindex specific index(es) and system catalogs at the same time\n"), progname);
  			exit(1);
  		}
  
*************** main(int argc, char *argv[])
*** 206,219 ****
  				dbname = get_user_name(progname);
  		}
  
! 		if (index)
! 			reindex_one_database(index, dbname, "INDEX", host, port,
! 								 username, prompt_password, progname, echo);
! 		if (table)
! 			reindex_one_database(table, dbname, "TABLE", host, port,
! 								 username, prompt_password, progname, echo);
! 		/* reindex database only if index or table is not specified */
! 		if (index == NULL && table == NULL)
  			reindex_one_database(dbname, dbname, "DATABASE", host, port,
  								 username, prompt_password, progname, echo);
  	}
--- 206,231 ----
  				dbname = get_user_name(progname);
  		}
  
! 		if (indexes.head != NULL)
! 		{
! 			SimpleStringListCell *cell;
! 			for (cell = indexes.head; cell; cell = cell->next)
! 			{
! 				reindex_one_database(cell->val, dbname, "INDEX", host, port,
! 									 username, prompt_password, progname, echo);
! 			}
! 		}
! 		if (tables.head != NULL)
! 		{
! 			SimpleStringListCell *cell;
! 			for (cell = tables.head; cell; cell = cell->next)
! 			{
! 				reindex_one_database(cell->val, dbname, "TABLE", host, port,
! 									 username, prompt_password, progname, echo);
! 			}
! 		}
! 		/* reindex database only if neither index nor table is specified */
! 		if (indexes.head == NULL && tables.head == NULL)
  			reindex_one_database(dbname, dbname, "DATABASE", host, port,
  								 username, prompt_password, progname, echo);
  	}
*************** help(const char *progname)
*** 331,340 ****
  	printf(_("  -a, --all                 reindex all databases\n"));
  	printf(_("  -d, --dbname=DBNAME       database to reindex\n"));
  	printf(_("  -e, --echo                show the commands being sent to the server\n"));
! 	printf(_("  -i, --index=INDEX         recreate specific index only\n"));
  	printf(_("  -q, --quiet               don't write any messages\n"));
  	printf(_("  -s, --system              reindex system catalogs\n"));
! 	printf(_("  -t, --table=TABLE         reindex specific table only\n"));
  	printf(_("  -V, --version             output version information, then exit\n"));
  	printf(_("  -?, --help                show this help, then exit\n"));
  	printf(_("\nConnection options:\n"));
--- 343,352 ----
  	printf(_("  -a, --all                 reindex all databases\n"));
  	printf(_("  -d, --dbname=DBNAME       database to reindex\n"));
  	printf(_("  -e, --echo                show the commands being sent to the server\n"));
! 	printf(_("  -i, --index=INDEX         recreate specific index(es) only\n"));
  	printf(_("  -q, --quiet               don't write any messages\n"));
  	printf(_("  -s, --system              reindex system catalogs\n"));
! 	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
  	printf(_("  -V, --version             output version information, then exit\n"));
  	printf(_("  -?, --help                show this help, then exit\n"));
  	printf(_("\nConnection options:\n"));
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
new file mode 100644
index eb28ad4..dc5fcaf
*** a/src/bin/scripts/vacuumdb.c
--- b/src/bin/scripts/vacuumdb.c
***************
*** 12,17 ****
--- 12,18 ----
  
  #include "postgres_fe.h"
  #include "common.h"
+ #include "dumputils.h"
  
  
  static void vacuum_one_database(const char *dbname, bool full, bool verbose,
*************** main(int argc, char *argv[])
*** 68,76 ****
  	bool		analyze_only = false;
  	bool		freeze = false;
  	bool		alldb = false;
- 	char	   *table = NULL;
  	bool		full = false;
  	bool		verbose = false;
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
--- 69,77 ----
  	bool		analyze_only = false;
  	bool		freeze = false;
  	bool		alldb = false;
  	bool		full = false;
  	bool		verbose = false;
+ 	SimpleStringList tables = {NULL, NULL};
  
  	progname = get_progname(argv[0]);
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
*************** main(int argc, char *argv[])
*** 118,124 ****
  				alldb = true;
  				break;
  			case 't':
! 				table = pg_strdup(optarg);
  				break;
  			case 'f':
  				full = true;
--- 119,125 ----
  				alldb = true;
  				break;
  			case 't':
! 				simple_string_list_append(&tables, optarg);
  				break;
  			case 'f':
  				full = true;
*************** main(int argc, char *argv[])
*** 181,189 ****
  					progname);
  			exit(1);
  		}
! 		if (table)
  		{
! 			fprintf(stderr, _("%s: cannot vacuum a specific table in all databases\n"),
  					progname);
  			exit(1);
  		}
--- 182,190 ----
  					progname);
  			exit(1);
  		}
! 		if (tables.head != NULL)
  		{
! 			fprintf(stderr, _("%s: cannot vacuum specific table(s) in all databases\n"),
  					progname);
  			exit(1);
  		}
*************** main(int argc, char *argv[])
*** 204,213 ****
  				dbname = get_user_name(progname);
  		}
  
! 		vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
! 							freeze, table,
! 							host, port, username, prompt_password,
! 							progname, echo);
  	}
  
  	exit(0);
--- 205,228 ----
  				dbname = get_user_name(progname);
  		}
  
! 		if (tables.head != NULL)
! 		{
! 			SimpleStringListCell *cell;
! 			for (cell = tables.head; cell; cell = cell->next)
! 			{
! 				vacuum_one_database(dbname, full, verbose, and_analyze,
! 									analyze_only,
! 									freeze, cell->val,
! 									host, port, username, prompt_password,
! 									progname, echo);
! 			}
! 		}
! 		else
! 			vacuum_one_database(dbname, full, verbose, and_analyze,
! 								analyze_only,
! 								freeze, NULL,
! 								host, port, username, prompt_password,
! 								progname, echo);
  	}
  
  	exit(0);
*************** help(const char *progname)
*** 348,354 ****
  	printf(_("  -f, --full                      do full vacuuming\n"));
  	printf(_("  -F, --freeze                    freeze row transaction information\n"));
  	printf(_("  -q, --quiet                     don't write any messages\n"));
! 	printf(_("  -t, --table='TABLE[(COLUMNS)]'  vacuum specific table only\n"));
  	printf(_("  -v, --verbose                   write a lot of output\n"));
  	printf(_("  -V, --version                   output version information, then exit\n"));
  	printf(_("  -z, --analyze                   update optimizer statistics\n"));
--- 363,369 ----
  	printf(_("  -f, --full                      do full vacuuming\n"));
  	printf(_("  -F, --freeze                    freeze row transaction information\n"));
  	printf(_("  -q, --quiet                     don't write any messages\n"));
! 	printf(_("  -t, --table='TABLE[(COLUMNS)]'  vacuum specific table(s) only\n"));
  	printf(_("  -v, --verbose                   write a lot of output\n"));
  	printf(_("  -V, --version                   output version information, then exit\n"));
  	printf(_("  -z, --analyze                   update optimizer statistics\n"));
