mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
253 lines
7.3 KiB
Bash
253 lines
7.3 KiB
Bash
#!/bin/sh
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
# Package : reindexdb Version : $Revision: 1.5 $
|
|
# Date : 05/08/2002 Author : Shaun Thomas
|
|
# Req : psql, sh, perl, sed Type : Utility
|
|
#
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
# Function Definitions
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
|
|
usage()
|
|
{
|
|
echo "$CMDNAME reindexes a PostgreSQL database."
|
|
echo
|
|
echo "Usage:"
|
|
echo " $CMDNAME [options] [dbname]"
|
|
echo
|
|
echo "Options:"
|
|
echo " -h, --host=HOSTNAME Database server host"
|
|
echo " -p, --port=PORT Database server port"
|
|
echo " -U, --username=USERNAME Username to connect as"
|
|
echo " -W, --password Prompt for password"
|
|
echo " -d, --dbname=DBNAME Database to reindex"
|
|
echo " -a, --all Reindex all databases"
|
|
echo " -t, --table=TABLE Reindex specific table only"
|
|
echo " -i, --index=INDEX Reindex specific index only"
|
|
echo " -e, --echo Show the command(s) sent to the backend"
|
|
echo " -q, --quiet Don't write any output"
|
|
echo
|
|
echo "Read the description of the SQL command REINDEX for details."
|
|
echo
|
|
exit 0
|
|
}
|
|
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
# Program Body
|
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
|
|
|
|
CMDNAME=`basename "$0"`
|
|
PATHNAME=`echo $0 | sed "s,$CMDNAME\$,,"`
|
|
|
|
# Try valiantly to get the location of psql, since you can't ever
|
|
# really know where it has been placed. We'll start by trying the
|
|
# path. If that fails, we'll try the directory where this script
|
|
# resides. Then on to whereis, and finally locate. Wish us luck.
|
|
|
|
if x=`psql -V 2>/dev/null | grep psql`; then
|
|
PSQL='psql'
|
|
elif [ -f ${PATHNAME}psql ]; then
|
|
PSQL=${PATHNAME}psql;
|
|
elif x=`whereis -b psql 2>/dev/null | sed 's/.* //'`; then
|
|
PSQL=$x
|
|
elif x=`locate -r bin/psql$ -n 1 2>/dev/null`; then
|
|
PSQL=$x
|
|
else
|
|
echo "$CMDNAME: Could not find psql to talk to postgres installation."
|
|
echo "Please make sure psql is in your path, or that this script is in"
|
|
echo "the same directory as psql was installed."
|
|
exit 1
|
|
fi
|
|
|
|
# Now, go through all of our command-line options and get each operation
|
|
# we said we'd accept in the usage listing.
|
|
|
|
while [ "$#" -gt 0 ]
|
|
do
|
|
# Show help.
|
|
case "$1" in
|
|
--help|-\?)
|
|
usage
|
|
exit 0
|
|
;;
|
|
|
|
# All of the following are postgres options. We can pass them on
|
|
# directly, without interpreting them in any way. We don't care.
|
|
# Anything that allows a space, we'll get the next *two* arguments
|
|
# and make sure to pass those along.
|
|
|
|
--host|-h|-p|--port|-U|--username)
|
|
PSQLOPT="$PSQLOPT $1 $2"
|
|
shift
|
|
;;
|
|
-h*|--host=*|-p*|--port=*|-U*|--username=*|-W|--password)
|
|
PSQLOPT="$PSQLOPT $1"
|
|
;;
|
|
|
|
# From this point on, we're setting options that are required for
|
|
# or only valid in This script. This includes which database(s) to
|
|
# reindex, which tables, or which indexes, and so on.
|
|
|
|
# Echoing. We'll *not* use this in queries we use to get lists.
|
|
--echo|-e)
|
|
ECHOOPT="-e"
|
|
;;
|
|
|
|
# Do not echo messages.
|
|
--quiet|-q)
|
|
ECHOOPT="-q"
|
|
quiet=1
|
|
;;
|
|
|
|
# Reindex all databases, all tables, all applicable indexes.
|
|
--all|-a)
|
|
alldb=1
|
|
;;
|
|
|
|
# Database to connect to, if not all of them.
|
|
--dbname|-d)
|
|
dbname="$2"
|
|
shift
|
|
;;
|
|
-d*)
|
|
dbname=`echo "$1" | sed 's/^-d/'`
|
|
;;
|
|
--dbname=*)
|
|
dbname=`echo "$1" | sed 's/^--dbname=//'`
|
|
;;
|
|
|
|
# Reindex specific Table. Disables index reindexing.
|
|
--table|-t)
|
|
table="$2"
|
|
shift
|
|
;;
|
|
-t*)
|
|
table=`echo "$1" | sed 's/^-t//'`
|
|
;;
|
|
--table=*)
|
|
table=`echo "$1" | sed 's/^--table=//'`
|
|
;;
|
|
|
|
# Reindex specific index. Disables table reindexing.
|
|
--index|-i)
|
|
index="$2"
|
|
shift
|
|
;;
|
|
-i*)
|
|
index=`echo "$1" | sed 's/^-i//'`
|
|
;;
|
|
--index=*)
|
|
index=`echo "$1" | sed 's/^--index=//'`
|
|
;;
|
|
|
|
# Yeah, no options? Whine, and show usage.
|
|
-*)
|
|
echo "$CMDNAME: invalid option: $1" 1>&2
|
|
usage;
|
|
exit 1
|
|
;;
|
|
|
|
# Finally, it's possible that the database name was just the last
|
|
# unlabeled option. So, let's get that.
|
|
*)
|
|
dbname="$1"
|
|
;;
|
|
esac
|
|
|
|
shift # Shift off each argument as we loop.
|
|
|
|
done
|
|
|
|
# Get a list of all databases we'll be using. This first case is if we
|
|
# were asked to do all databases.
|
|
if [ "$alldb" ]; then
|
|
|
|
if [ "$dbname" ] || [ "$index" ] || [ "$table" ]; then
|
|
echo "$CMDNAME: cannot reindex all databases and a specific database," 1>&2
|
|
echo " table, or index at the same time." 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Execute a command to pull back all databases the user specified can
|
|
# connect to. That's the list we'll be using. It's also why it's
|
|
# a good idea for this to be run as a super-user.
|
|
sql='SELECT datname FROM pg_database WHERE datallowconn'
|
|
dbname=`$PSQL $PSQLOPT -q -t -A -d template1 -c "$sql"`
|
|
|
|
# Ok, if it's not all databases, make sure at least one database is
|
|
# specified before continuing.
|
|
elif [ -z "$dbname" ]; then
|
|
echo "$CMDNAME: missing required argument: database name" 1>&2
|
|
usage;
|
|
exit 1
|
|
fi
|
|
|
|
# No. We can't reindex a specific index and table at the same time.
|
|
# Complain about this, and move on.
|
|
if [ "$table" ] && [ "$index" ]; then
|
|
echo "$CMDNAME: cannot reindex a specific table and a specific index" 1>&2
|
|
echo "at the same time." 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# If index was selected, reindex that index.
|
|
if [ "$index" ]; then
|
|
$PSQL $PSQLOPT $ECHOOPT -c "REINDEX INDEX \"$index\"" -d "$dbname"
|
|
if [ "$?" -ne 0 ]; then
|
|
echo "$CMDNAME: reindex index \"$index\" failed" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# Ok, no index. Is there a specific table to reindex?
|
|
elif [ "$table" ]; then
|
|
$PSQL $PSQLOPT $ECHOOPT -c "REINDEX TABLE \"$table\"" -d "$dbname"
|
|
if [ "$?" -ne 0 ]; then
|
|
echo "$CMDNAME: reindex table \"$table\" failed" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
# No specific table, no specific index, either we have a specific database,
|
|
# or were told to do all databases. Do it!
|
|
else
|
|
|
|
# We set IFS to newline only so that the for-loops won't misinterpret
|
|
# spaces in the lists we retrieved via psql. Note also the use of
|
|
# regclass to handle spaces, mixed-case names, and schema awareness.
|
|
sql="SELECT DISTINCT c.oid::pg_catalog.regclass FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class c ON c.oid = x.indrelid JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE nspname NOT LIKE 'pg\\\\_%'"
|
|
|
|
IFS='
|
|
'
|
|
for db in $dbname; do
|
|
|
|
# Only print which database we're currently reindexing if not in
|
|
# quiet mode, and we're doing more than one database.
|
|
[ "$alldb" ] && [ -z "$quiet" ] && echo "Reindexing $db"
|
|
|
|
IFS='
|
|
'
|
|
# Get a list of non-system tables that have indexes.
|
|
tables=`$PSQL $PSQLOPT -q -t -A -d "$db" -c "$sql"`
|
|
|
|
# Ok, reindex every table in the database.
|
|
IFS='
|
|
'
|
|
for tab in $tables; do
|
|
IFS='
|
|
'
|
|
$PSQL $PSQLOPT $ECHOOPT -c "REINDEX TABLE $tab" -d "$db"
|
|
if [ "$?" -ne 0 ]; then
|
|
echo "$CMDNAME: reindex table $tab failed" 1>&2
|
|
exit 1
|
|
fi
|
|
IFS='
|
|
'
|
|
done
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
exit 0
|