Change clusterdb and vacuumdb into C programs.

This commit is contained in:
Peter Eisentraut 2003-06-18 12:19:11 +00:00
parent eab5d643b2
commit f374a9dae9
10 changed files with 552 additions and 389 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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:

View File

@ -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 <pgsql-bugs@postgresql.org>."
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

245
src/bin/scripts/clusterdb.c Normal file
View File

@ -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 <pgsql-bugs@postgresql.org>.\n"));
}

View File

@ -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

View File

@ -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 <pgsql-bugs@postgresql.org>."
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

272
src/bin/scripts/vacuumdb.c Normal file
View File

@ -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 <pgsql-bugs@postgresql.org>.\n"));
}