summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/maintenance.sgml4
-rw-r--r--doc/src/sgml/ref/clusterdb.sgml19
-rw-r--r--doc/src/sgml/ref/dropuser.sgml16
-rw-r--r--doc/src/sgml/ref/vacuumdb.sgml19
-rw-r--r--src/bin/scripts/Makefile13
-rw-r--r--src/bin/scripts/clusterdb168
-rw-r--r--src/bin/scripts/clusterdb.c245
-rw-r--r--src/bin/scripts/nls.mk3
-rw-r--r--src/bin/scripts/vacuumdb182
-rw-r--r--src/bin/scripts/vacuumdb.c272
10 files changed, 552 insertions, 389 deletions
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 353b8cf2f36..122137ad2b9 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.22 2003/03/25 16:15:37 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.23 2003/06/18 12:19:11 petere Exp $
-->
<chapter id="maintenance">
@@ -136,7 +136,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.22 2003/03/25 16:15:37
<command>VACUUM</> once a day at a low-usage time of day, supplemented
by more frequent vacuuming of heavily-updated tables if necessary.
(If you have multiple databases in a cluster, don't forget to
- vacuum each one; the <filename>vacuumdb</> script may be helpful.)
+ vacuum each one; the program <filename>vacuumdb</> may be helpful.)
Use plain <command>VACUUM</>, not <command>VACUUM FULL</>, for routine
vacuuming for space recovery.
</para>
diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml
index 4200481c1da..eb814261876 100644
--- a/doc/src/sgml/ref/clusterdb.sgml
+++ b/doc/src/sgml/ref/clusterdb.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/clusterdb.sgml,v 1.9 2003/03/24 14:32:51 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/clusterdb.sgml,v 1.10 2003/06/18 12:19:11 petere Exp $
PostgreSQL documentation
-->
@@ -41,16 +41,13 @@ PostgreSQL documentation
</para>
<para>
- <application>clusterdb</application> is a shell script wrapper around the
- backend command
- <xref linkend="SQL-CLUSTER" endterm="sql-cluster-title"> via
- the <productname>PostgreSQL</productname> interactive terminal
- <xref linkend="APP-PSQL">. There is no effective
- difference between clustering databases via this or other methods.
- <application>psql</application> must be found by the script and
- a database server must be running at the targeted host. Also, any default
- settings and environment variables available to <application>psql</application>
- and the <application>libpq</application> front-end library do apply.
+ <application>clusterdb</application> is a wrapper around the SQL
+ command <xref linkend="SQL-CLUSTER" endterm="sql-cluster-title">.
+ There is no effective difference between clustering databases via
+ this or other methods. The database server must be running at the
+ targeted host. Also, any default settings and environment
+ variables used by the <application>libpq</application> front-end
+ library will apply.
</para>
</refsect1>
diff --git a/doc/src/sgml/ref/dropuser.sgml b/doc/src/sgml/ref/dropuser.sgml
index d781b2a64f1..24e8d8ecf45 100644
--- a/doc/src/sgml/ref/dropuser.sgml
+++ b/doc/src/sgml/ref/dropuser.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropuser.sgml,v 1.25 2003/05/26 17:50:09 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropuser.sgml,v 1.26 2003/06/18 12:19:11 petere Exp $
PostgreSQL documentation
-->
@@ -37,13 +37,13 @@ PostgreSQL documentation
</para>
<para>
- <application>dropuser</application> is a shell script wrapper
- around the <acronym>SQL</acronym> command <xref
- linkend="SQL-DROPUSER" endterm="SQL-DROPUSER-title">. The database
- server must be running on the targeted host. There
- is nothing special about removing users via this or other
- methods. Also, any default settings and environment variables
- used by the <application>libpq</application> front-end library will apply.
+ <application>dropuser</application> is a wrapper around the
+ <acronym>SQL</acronym> command <xref linkend="SQL-DROPUSER"
+ endterm="SQL-DROPUSER-title">. The database server must be running
+ on the targeted host. There is nothing special about removing
+ users via this or other methods. Also, any default settings and
+ environment variables used by the <application>libpq</application>
+ front-end library will apply.
</para>
</refsect1>
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
index 84583e9aea3..e04cf16c3fe 100644
--- a/doc/src/sgml/ref/vacuumdb.sgml
+++ b/doc/src/sgml/ref/vacuumdb.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.28 2003/03/24 14:32:51 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.29 2003/06/18 12:19:11 petere Exp $
PostgreSQL documentation
-->
@@ -48,16 +48,13 @@ PostgreSQL documentation
</para>
<para>
- <application>vacuumdb</application> is a shell script wrapper around the
- backend command
- <xref linkend="SQL-VACUUM" endterm="SQL-VACUUM-title"> via
- the <productname>PostgreSQL</productname> interactive terminal
- <xref linkend="APP-PSQL">. There is no effective
- difference between vacuuming databases via this or other methods.
- <application>psql</application> must be found by the script and
- a database server must be running at the targeted host. Also, any default
- settings and environment variables available to <application>psql</application>
- and the <application>libpq</application> front-end library do apply.
+ <application>vacuumdb</application> is a wrapper around the SQL
+ command <xref linkend="SQL-VACUUM" endterm="SQL-VACUUM-title">.
+ There is no effective difference between vacuuming databases via
+ this or other methods. The database server must be running at the
+ targeted host. Also, any default settings and environment
+ variables used by the <application>libpq</application> front-end
+ library will apply.
</para>
diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile
index 79b60940dc6..66f13c45333 100644
--- a/src/bin/scripts/Makefile
+++ b/src/bin/scripts/Makefile
@@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
-# $Header: /cvsroot/pgsql/src/bin/scripts/Makefile,v 1.20 2003/04/16 05:23:55 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/scripts/Makefile,v 1.21 2003/06/18 12:19:11 petere Exp $
#
#-------------------------------------------------------------------------
@@ -13,8 +13,7 @@ subdir = src/bin/scripts
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-SCRIPTS := vacuumdb clusterdb
-PROGRAMS = createdb createlang createuser dropdb droplang dropuser
+PROGRAMS = createdb createlang createuser dropdb droplang dropuser clusterdb vacuumdb
override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS)
@@ -30,6 +29,8 @@ createuser: createuser.o common.o dumputils.o sprompt.o $(top_builddir)/src/back
dropdb: dropdb.o common.o dumputils.o sprompt.o $(top_builddir)/src/backend/parser/keywords.o
droplang: droplang.o common.o sprompt.o print.o mbprint.o
dropuser: dropuser.o common.o dumputils.o sprompt.o $(top_builddir)/src/backend/parser/keywords.o
+clusterdb: clusterdb.o common.o dumputils.o sprompt.o $(top_builddir)/src/backend/parser/keywords.o
+vacuumdb: vacuumdb.o common.o sprompt.o
dumputils.c sprompt.c : % : $(top_srcdir)/src/bin/pg_dump/%
rm -f $@ && $(LN_S) $< .
@@ -49,14 +50,14 @@ install: all installdirs
$(INSTALL_PROGRAM) droplang$(X) $(DESTDIR)$(bindir)/droplang$(X)
$(INSTALL_PROGRAM) createuser$(X) $(DESTDIR)$(bindir)/createuser$(X)
$(INSTALL_PROGRAM) dropuser$(X) $(DESTDIR)$(bindir)/dropuser$(X)
- $(INSTALL_SCRIPT) $(srcdir)/clusterdb $(DESTDIR)$(bindir)/clusterdb
- $(INSTALL_SCRIPT) $(srcdir)/vacuumdb $(DESTDIR)$(bindir)/vacuumdb
+ $(INSTALL_PROGRAM) clusterdb$(X) $(DESTDIR)$(bindir)/clusterdb$(X)
+ $(INSTALL_PROGRAM) vacuumdb$(X) $(DESTDIR)$(bindir)/vacuumdb$(X)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
uninstall:
- rm -f $(addprefix $(DESTDIR)$(bindir)/, $(SCRIPTS) $(addsuffix $(X), $(PROGRAMS)))
+ rm -f $(addprefix $(DESTDIR)$(bindir)/, $(addsuffix $(X), $(PROGRAMS)))
clean distclean maintainer-clean:
diff --git a/src/bin/scripts/clusterdb b/src/bin/scripts/clusterdb
deleted file mode 100644
index 70386bf7799..00000000000
--- a/src/bin/scripts/clusterdb
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/bin/sh
-#-------------------------------------------------------------------------
-#
-# clusterdb--
-# cluster a postgres database
-#
-# This script runs psql with the "-c" option to cluster
-# the requested database.
-#
-# Copyright (c) 2002, PostgreSQL Global Development Group
-#
-#
-# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/clusterdb,v 1.12 2003/06/11 05:13:12 momjian Exp $
-#
-#-------------------------------------------------------------------------
-
-CMDNAME=`basename "$0"`
-PATHNAME=`echo "$0" | sed "s,$CMDNAME\$,,"`
-
-PSQLOPT=
-table=
-dbname=
-alldb=
-quiet=0
-
-while [ "$#" -gt 0 ]
-do
- case "$1" in
- --help|-\?)
- usage=t
- break
- ;;
-# options passed on to psql
- --host|-h)
- PSQLOPT="$PSQLOPT -h $2"
- shift;;
- -h*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --host=*)
- PSQLOPT="$PSQLOPT -h `echo \"$1\" | sed 's/^--host=//'`"
- ;;
- --port|-p)
- PSQLOPT="$PSQLOPT -p $2"
- shift;;
- -p*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --port=*)
- PSQLOPT="$PSQLOPT -p `echo \"$1\" | sed 's/^--port=//'`"
- ;;
- --username|-U)
- PSQLOPT="$PSQLOPT -U $2"
- shift;;
- -U*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --username=*)
- PSQLOPT="$PSQLOPT -U `echo \"$1\" | sed 's/^--username=//'`"
- ;;
- --password|-W)
- PSQLOPT="$PSQLOPT -W"
- ;;
- --echo|-e)
- ECHOOPT="-e"
- ;;
- --quiet|-q)
- ECHOOPT="$ECHOOPT -o /dev/null"
- quiet=1
- ;;
- --dbname|-d)
- dbname="$2"
- shift;;
- -d*)
- dbname=`echo $1 | sed 's/^-d//'`
- ;;
- --dbname=*)
- dbname=`echo $1 | sed 's/^--dbname=//'`
- ;;
- -a|--alldb)
- alldb=1
- ;;
-# options converted into SQL command
- --table|-t)
- table="$2"
- shift;;
- -t*)
- table=`echo $1 | sed 's/^-t//'`
- ;;
- --table=*)
- table=`echo $1 | sed 's/^--table=//'`
- ;;
- -*)
- echo "$CMDNAME: invalid option: $1" 1>&2
- echo "Try '$CMDNAME --help' for more information." 1>&2
- exit 1
- ;;
- *)
- dbname="$1"
- if [ "$#" -ne 1 ]; then
- echo "$CMDNAME: invalid option: $2" 1>&2
- echo "Try '$CMDNAME --help' for more information." 1>&2
- exit 1
- fi
- ;;
- esac
- shift
-done
-
-if [ "$usage" ]; then
- echo "$CMDNAME cluster all previously clustered tables in a database."
- echo
- echo "Usage:"
- echo " $CMDNAME [OPTION]... [DBNAME]"
- echo
- echo "Options:"
- echo " -a, --all cluster all databases"
- echo " -d, --dbname=DBNAME database to cluster"
- echo " -t, --table='TABLE' cluster specific table only"
- echo " -e, --echo show the commands sent to the backend"
- echo " -q, --quiet don't write any output"
- echo " --help show this help, then exit"
- echo
- echo "Connection options:"
- echo " -h, --host=HOSTNAME database server host or socket directory"
- echo " -p, --port=PORT database server port"
- echo " -U, --username=USERNAME user name to connect as"
- echo " -W, --password prompt for password"
- echo
- echo "Read the description of the SQL command CLUSTER for details."
- echo
- echo "Report bugs to <[email protected]>."
- exit 0
-fi
-
-if [ "$alldb" ]; then
- if [ "$dbname" -o "$table" ]; then
- echo "$CMDNAME: cannot cluster all databases and a specific one at the same time" 1>&2
- exit 1
- fi
- dbname=`${PATHNAME}psql $PSQLOPT -q -t -A -d template1 -c 'SELECT datname FROM pg_database WHERE datallowconn'`
- [ "$?" -ne 0 ] && exit 1
-
-elif [ -z "$dbname" ]; then
- if [ "$PGDATABASE" ]; then
- dbname="$PGDATABASE"
- elif [ "$PGUSER" ]; then
- dbname="$PGUSER"
- else
- dbname=`${PATHNAME}pg_id -u -n`
- fi
- [ "$?" -ne 0 ] && exit 1
-fi
-
-for db in $dbname
-do
- [ "$alldb" ] && echo "Clustering $db"
- if [ -z "$table" ]; then
- ${PATHNAME}psql $PSQLOPT $ECHOOPT -c "CLUSTER" -d $db
- [ "$?" -ne 0 ] && exit 1
- else
- ${PATHNAME}psql $PSQLOPT $ECHOOPT -c "CLUSTER $table" -d $db
- [ "$?" -ne 0 ] && exit 1
- fi
-done
-
-exit 0
diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c
new file mode 100644
index 00000000000..41cdfc486f9
--- /dev/null
+++ b/src/bin/scripts/clusterdb.c
@@ -0,0 +1,245 @@
+/*-------------------------------------------------------------------------
+ *
+ * clusterdb
+ *
+ * Portions Copyright (c) 2002-2003, PostgreSQL Global Development Group
+ *
+ * $Header: /cvsroot/pgsql/src/bin/scripts/clusterdb.c,v 1.1 2003/06/18 12:19:11 petere Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+#include "common.h"
+#include "dumputils.h"
+
+
+static
+void cluster_one_database(const char *dbname, const char *table,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet);
+static
+void cluster_all_databases(const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet);
+
+static void help(const char *progname);
+
+
+int
+main(int argc, char *argv[])
+{
+ static struct option long_options[] = {
+ {"host", required_argument, NULL, 'h'},
+ {"port", required_argument, NULL, 'p'},
+ {"username", required_argument, NULL, 'U'},
+ {"password", no_argument, NULL, 'W'},
+ {"echo", no_argument, NULL, 'e'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"dbname", required_argument, NULL, 'd'},
+ {"all", no_argument, NULL, 'a'},
+ {"table", required_argument, NULL, 't'},
+ {NULL, 0, NULL, 0}
+ };
+
+ char *progname;
+ int optindex;
+ int c;
+
+ const char *dbname = NULL;
+ char *host = NULL;
+ char *port = NULL;
+ char *username = NULL;
+ bool password = false;
+ bool echo = false;
+ bool quiet = false;
+ bool alldb = false;
+ char *table = NULL;
+
+ progname = get_progname(argv[0]);
+ init_nls();
+ handle_help_version_opts(argc, argv, "clusterdb", help);
+
+ while ((c = getopt_long(argc, argv, "h:p:U:Weqd:at:", long_options, &optindex)) != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ host = optarg;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'U':
+ username = optarg;
+ break;
+ case 'W':
+ password = true;
+ break;
+ case 'e':
+ echo = true;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'd':
+ dbname = optarg;
+ break;
+ case 'a':
+ alldb = true;
+ break;
+ case 't':
+ table = optarg;
+ break;
+ default:
+ fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+ exit(1);
+ }
+ }
+
+ switch (argc - optind)
+ {
+ case 0:
+ break;
+ case 1:
+ dbname = argv[optind];
+ break;
+ default:
+ fprintf(stderr, _("%s: too many command-line arguments (first is '%s')\n"),
+ progname, argv[optind + 1]);
+ fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (alldb)
+ {
+ if (dbname)
+ {
+ fprintf(stderr, _("%s: cannot cluster all databases and a specific one at the same time\n"),
+ progname);
+ exit(1);
+ }
+ if (table)
+ {
+ fprintf(stderr, _("%s: cannot cluster a specific table in all databases\n"),
+ progname);
+ exit(1);
+ }
+
+ cluster_all_databases(host, port, username, password,
+ progname, echo, quiet);
+ }
+ else
+ {
+ if (dbname == NULL)
+ {
+ if (getenv("PGDATABASE"))
+ dbname = getenv("PGDATABASE");
+ else if (getenv("PGUSER"))
+ dbname = getenv("PGUSER");
+ else
+ dbname = get_user_name(progname);
+ }
+
+ cluster_one_database(dbname, table,
+ host, port, username, password,
+ progname, echo, quiet);
+ }
+
+ exit(0);
+}
+
+
+static
+void cluster_one_database(const char *dbname, const char *table,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet)
+{
+ PQExpBufferData sql;
+
+ PGconn *conn;
+ PGresult *result;
+
+ initPQExpBuffer(&sql);
+
+ appendPQExpBuffer(&sql, "CLUSTER");
+ if (table)
+ appendPQExpBuffer(&sql, " %s", fmtId(table));
+ appendPQExpBuffer(&sql, ";\n");
+
+ conn = connectDatabase(dbname, host, port, username, password, progname);
+
+ if (echo)
+ printf("%s", sql.data);
+ result = PQexec(conn, sql.data);
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ if (table)
+ fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"),
+ progname, table, dbname, PQerrorMessage(conn));
+ else
+ fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"),
+ progname, dbname, PQerrorMessage(conn));
+ PQfinish(conn);
+ exit(1);
+ }
+
+ PQclear(result);
+ PQfinish(conn);
+ termPQExpBuffer(&sql);
+
+ if (!quiet)
+ puts("CLUSTER");
+}
+
+
+static
+void cluster_all_databases(const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet)
+{
+ PGconn *conn;
+ PGresult *result;
+ int i;
+
+ conn = connectDatabase("template1", host, port, username, password, progname);
+ result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn;", progname, echo);
+ PQfinish(conn);
+
+ for (i = 0; i < PQntuples(result); i++)
+ {
+ char *dbname = PQgetvalue(result, i, 0);
+
+ if (!quiet)
+ fprintf(stderr, _("%s: clustering database \"%s\"\n"), progname, dbname);
+
+ cluster_one_database(dbname, NULL,
+ host, port, username, password,
+ progname, echo, quiet);
+ }
+
+ PQclear(result);
+}
+
+
+static void
+help(const char *progname)
+{
+ printf(_("%s clusters all previously clustered tables in a database.\n"), progname);
+ printf(_("Usage:\n"));
+ printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
+ printf(_("\nOptions:\n"));
+ printf(_(" -a, --all cluster all databases\n"));
+ printf(_(" -d, --dbname=DBNAME database to cluster\n"));
+ printf(_(" -t, --table=TABLE cluster specific table only"));
+ printf(_(" -e, --echo show the commands being sent to the server\n"));
+ printf(_(" -q, --quiet don't write any messages\n"));
+ printf(_(" --help show this help, then exit\n"));
+ printf(_(" --version output version information, then exit\n"));
+ printf(_("\nConnection options:\n"));
+ printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
+ printf(_(" -p, --port=PORT database server port\n"));
+ printf(_(" -U, --username=USERNAME user name to connect as\n"));
+ printf(_(" -W, --password prompt for password\n"));
+ printf(_("\nRead the description of the SQL command CLUSTER for details.\n"));
+ printf(_("\nReport bugs to <[email protected]>.\n"));
+}
diff --git a/src/bin/scripts/nls.mk b/src/bin/scripts/nls.mk
index 365b8797274..260afe29449 100644
--- a/src/bin/scripts/nls.mk
+++ b/src/bin/scripts/nls.mk
@@ -1,7 +1,8 @@
-# $Header: /cvsroot/pgsql/src/bin/scripts/nls.mk,v 1.1 2003/03/18 22:19:47 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/scripts/nls.mk,v 1.2 2003/06/18 12:19:11 petere Exp $
CATALOG_NAME := pgscripts
AVAIL_LANGUAGES :=
GETTEXT_FILES := createdb.c createlang.c createuser.c \
dropdb.c droplang.c dropuser.c \
+ clusterdb.c vacuumdb.c \
common.c
GETTEXT_TRIGGERS:= _ simple_prompt
diff --git a/src/bin/scripts/vacuumdb b/src/bin/scripts/vacuumdb
deleted file mode 100644
index 7b002a8fb6c..00000000000
--- a/src/bin/scripts/vacuumdb
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/bin/sh
-#-------------------------------------------------------------------------
-#
-# vacuumdb--
-# vacuum a postgres database
-#
-# This script runs psql with the "-c" option to vacuum
-# the requested database.
-#
-# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
-# Portions Copyright (c) 1994, Regents of the University of California
-#
-#
-# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/vacuumdb,v 1.28 2003/06/11 05:13:12 momjian Exp $
-#
-#-------------------------------------------------------------------------
-
-CMDNAME=`basename "$0"`
-PATHNAME=`echo "$0" | sed "s,$CMDNAME\$,,"`
-
-PSQLOPT=
-full=
-verbose=
-analyze=
-table=
-dbname=
-alldb=
-quiet=0
-
-while [ "$#" -gt 0 ]
-do
- case "$1" in
- --help|-\?)
- usage=t
- break
- ;;
-# options passed on to psql
- --host|-h)
- PSQLOPT="$PSQLOPT -h $2"
- shift;;
- -h*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --host=*)
- PSQLOPT="$PSQLOPT -h `echo \"$1\" | sed 's/^--host=//'`"
- ;;
- --port|-p)
- PSQLOPT="$PSQLOPT -p $2"
- shift;;
- -p*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --port=*)
- PSQLOPT="$PSQLOPT -p `echo \"$1\" | sed 's/^--port=//'`"
- ;;
- --username|-U)
- PSQLOPT="$PSQLOPT -U $2"
- shift;;
- -U*)
- PSQLOPT="$PSQLOPT $1"
- ;;
- --username=*)
- PSQLOPT="$PSQLOPT -U `echo \"$1\" | sed 's/^--username=//'`"
- ;;
- --password|-W)
- PSQLOPT="$PSQLOPT -W"
- ;;
- --echo|-e)
- ECHOOPT="-e"
- ;;
- --quiet|-q)
- ECHOOPT="$ECHOOPT -o /dev/null"
- quiet=1
- ;;
- --dbname|-d)
- dbname="$2"
- shift;;
- -d*)
- dbname=`echo $1 | sed 's/^-d//'`
- ;;
- --dbname=*)
- dbname=`echo $1 | sed 's/^--dbname=//'`
- ;;
-# options converted into SQL command
- --analyze|-z)
- analyze="ANALYZE"
- ;;
- --all|-a)
- alldb=Y
- ;;
- --table|-t)
- table="$2"
- shift;;
- -t*)
- table=`echo $1 | sed 's/^-t//'`
- ;;
- --table=*)
- table=`echo $1 | sed 's/^--table=//'`
- ;;
- --full|-f)
- full="FULL"
- ;;
- --verbose|-v)
- verbose="VERBOSE"
- ;;
-
- -*)
- echo "$CMDNAME: invalid option: $1" 1>&2
- echo "Try '$CMDNAME --help' for more information." 1>&2
- exit 1
- ;;
- *)
- dbname="$1"
- if [ "$#" -ne 1 ]; then
- echo "$CMDNAME: invalid option: $2" 1>&2
- echo "Try '$CMDNAME --help' for more information." 1>&2
- exit 1
- fi
- ;;
- esac
- shift
-done
-
-if [ "$usage" ]; then
- echo "$CMDNAME cleans and analyzes a PostgreSQL database."
- echo
- echo "Usage:"
- echo " $CMDNAME [OPTION]... [DBNAME]"
- echo
- echo "Options:"
- echo " -a, --all vacuum all databases"
- echo " -d, --dbname=DBNAME database to vacuum"
- echo " -t, --table='TABLE[(columns)]' vacuum specific table only"
- echo " -f, --full do full vacuuming"
- echo " -z, --analyze update optimizer hints"
- echo " -e, --echo show the command being sent to the backend"
- echo " -q, --quiet don't write any output"
- echo " -v, --verbose write a lot of output"
- echo " --help show this help, then exit"
- echo
- echo "Connection options:"
- echo " -h, --host=HOSTNAME database server host or socket directory"
- echo " -p, --port=PORT database server port"
- echo " -U, --username=USERNAME user name to connect as"
- echo " -W, --password prompt for password"
- echo
- echo "Read the description of the SQL command VACUUM for details."
- echo
- echo "Report bugs to <[email protected]>."
- exit 0
-fi
-
-if [ "$alldb" ]; then
- if [ "$dbname" -o "$table" ]; then
- echo "$CMDNAME: cannot vacuum all databases and a specific one at the same time" 1>&2
- exit 1
- fi
- dbname=`${PATHNAME}psql $PSQLOPT -q -t -A -d template1 -c 'SELECT datname FROM pg_database WHERE datallowconn'`
-
-elif [ -z "$dbname" ]; then
- if [ "$PGDATABASE" ]; then
- dbname="$PGDATABASE"
- elif [ "$PGUSER" ]; then
- dbname="$PGUSER"
- else
- dbname=`${PATHNAME}pg_id -u -n`
- fi
- [ "$?" -ne 0 ] && exit 1
-fi
-
-for db in $dbname
-do
- [ "$alldb" -a "$quiet" -ne 1 ] && echo "Vacuuming $db"
- ${PATHNAME}psql $PSQLOPT $ECHOOPT -c "VACUUM $full $verbose $analyze $table" -d $db
- if [ "$?" -ne 0 ]; then
- echo "$CMDNAME: vacuum $table $db failed" 1>&2
- exit 1
- fi
-done
-
-exit 0
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
new file mode 100644
index 00000000000..88729ef236d
--- /dev/null
+++ b/src/bin/scripts/vacuumdb.c
@@ -0,0 +1,272 @@
+/*-------------------------------------------------------------------------
+ *
+ * vacuumdb
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Header: /cvsroot/pgsql/src/bin/scripts/vacuumdb.c,v 1.1 2003/06/18 12:19:11 petere Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+#include "common.h"
+
+
+static
+void vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, const char *table,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet);
+static
+void vacuum_all_databases(bool full, bool verbose, bool analyze,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet);
+
+static void help(const char *progname);
+
+
+int
+main(int argc, char *argv[])
+{
+ static struct option long_options[] = {
+ {"host", required_argument, NULL, 'h'},
+ {"port", required_argument, NULL, 'p'},
+ {"username", required_argument, NULL, 'U'},
+ {"password", no_argument, NULL, 'W'},
+ {"echo", no_argument, NULL, 'e'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"dbname", required_argument, NULL, 'd'},
+ {"analyze", no_argument, NULL, 'z'},
+ {"all", no_argument, NULL, 'a'},
+ {"table", required_argument, NULL, 't'},
+ {"full", no_argument, NULL, 'f'},
+ {"verbose", no_argument, NULL, 'v'},
+ {NULL, 0, NULL, 0}
+ };
+
+ char *progname;
+ int optindex;
+ int c;
+
+ const char *dbname = NULL;
+ char *host = NULL;
+ char *port = NULL;
+ char *username = NULL;
+ bool password = false;
+ bool echo = false;
+ bool quiet = false;
+ bool analyze = false;
+ bool alldb = false;
+ char *table = NULL;
+ bool full = false;
+ bool verbose = false;
+
+ progname = get_progname(argv[0]);
+ init_nls();
+ handle_help_version_opts(argc, argv, "vacuumdb", help);
+
+ while ((c = getopt_long(argc, argv, "h:p:U:Weqd:zat:fv", long_options, &optindex)) != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ host = optarg;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'U':
+ username = optarg;
+ break;
+ case 'W':
+ password = true;
+ break;
+ case 'e':
+ echo = true;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'd':
+ dbname = optarg;
+ break;
+ case 'z':
+ analyze = true;
+ break;
+ case 'a':
+ alldb = true;
+ break;
+ case 't':
+ table = optarg;
+ break;
+ case 'f':
+ full = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+ exit(1);
+ }
+ }
+
+ switch (argc - optind)
+ {
+ case 0:
+ break;
+ case 1:
+ dbname = argv[optind];
+ break;
+ default:
+ fprintf(stderr, _("%s: too many command-line arguments (first is '%s')\n"),
+ progname, argv[optind + 1]);
+ fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (alldb)
+ {
+ if (dbname)
+ {
+ fprintf(stderr, _("%s: cannot vacuum all databases and a specific one at the same time\n"),
+ progname);
+ exit(1);
+ }
+ if (table)
+ {
+ fprintf(stderr, _("%s: cannot vacuum a specific table in all databases\n"),
+ progname);
+ exit(1);
+ }
+
+ vacuum_all_databases(full, verbose, analyze,
+ host, port, username, password,
+ progname, echo, quiet);
+ }
+ else
+ {
+ if (dbname == NULL)
+ {
+ if (getenv("PGDATABASE"))
+ dbname = getenv("PGDATABASE");
+ else if (getenv("PGUSER"))
+ dbname = getenv("PGUSER");
+ else
+ dbname = get_user_name(progname);
+ }
+
+ vacuum_one_database(dbname, full, verbose, analyze, table,
+ host, port, username, password,
+ progname, echo, quiet);
+ }
+
+ exit(0);
+}
+
+
+static
+void vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, const char *table,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet)
+{
+ PQExpBufferData sql;
+
+ PGconn *conn;
+ PGresult *result;
+
+ initPQExpBuffer(&sql);
+
+ appendPQExpBuffer(&sql, "VACUUM");
+ if (full)
+ appendPQExpBuffer(&sql, " FULL");
+ if (verbose)
+ appendPQExpBuffer(&sql, " VERBOSE");
+ if (analyze)
+ appendPQExpBuffer(&sql, " ANALYZE");
+ if (table)
+ appendPQExpBuffer(&sql, " %s", table);
+ appendPQExpBuffer(&sql, ";\n");
+
+ conn = connectDatabase(dbname, host, port, username, password, progname);
+
+ if (echo)
+ printf("%s", sql.data);
+ result = PQexec(conn, sql.data);
+
+ if (PQresultStatus(result) != PGRES_COMMAND_OK)
+ {
+ if (table)
+ fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
+ progname, table, dbname, PQerrorMessage(conn));
+ else
+ fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
+ progname, dbname, PQerrorMessage(conn));
+ PQfinish(conn);
+ exit(1);
+ }
+
+ PQclear(result);
+ PQfinish(conn);
+ termPQExpBuffer(&sql);
+
+ if (!quiet)
+ puts("VACUUM");
+}
+
+
+static
+void vacuum_all_databases(bool full, bool verbose, bool analyze,
+ const char *host, const char *port, const char *username, bool password,
+ const char *progname, bool echo, bool quiet)
+{
+ PGconn *conn;
+ PGresult *result;
+ int i;
+
+ conn = connectDatabase("template1", host, port, username, password, progname);
+ result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn;", progname, echo);
+ PQfinish(conn);
+
+ for (i = 0; i < PQntuples(result); i++)
+ {
+ char *dbname = PQgetvalue(result, i, 0);
+
+ if (!quiet)
+ fprintf(stderr, _("%s: vacuuming database \"%s\"\n"), progname, dbname);
+
+ vacuum_one_database(dbname, full, verbose, analyze, NULL,
+ host, port, username, password,
+ progname, echo, quiet);
+ }
+
+ PQclear(result);
+}
+
+
+static void
+help(const char *progname)
+{
+ printf(_("%s cleans and analyzes a PostgreSQL database.\n\n"), progname);
+ printf(_("Usage:\n"));
+ printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
+ printf(_("\nOptions:\n"));
+ printf(_(" -a, --all vacuum all databases\n"));
+ printf(_(" -d, --dbname=DBNAME database to vacuum\n"));
+ printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n"));
+ printf(_(" -f, --full do full vacuuming\n"));
+ printf(_(" -z, --analyze update optimizer hints\n"));
+ printf(_(" -e, --echo show the commands being sent to the server\n"));
+ printf(_(" -q, --quiet don't write any messages\n"));
+ printf(_(" -v, --verbose write a lot of output\n"));
+ printf(_(" --help show this help, then exit\n"));
+ printf(_(" --version output version information, then exit\n"));
+ printf(_("\nConnection options:\n"));
+ printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
+ printf(_(" -p, --port=PORT database server port\n"));
+ printf(_(" -U, --username=USERNAME user name to connect as\n"));
+ printf(_(" -W, --password prompt for password\n"));
+ printf(_("\nRead the description of the SQL command VACUUM for details.\n"));
+ printf(_("\nReport bugs to <[email protected]>.\n"));
+}