pg_plug
text/plain
#!/bin/sh
#-----------------------------------------------------------------------
# pg_plug -- painless upgrade
# PG 7.4 standard -> PG 7.4 with various enhancements
#
# 2003-10-04 mk new
# 2003-10-14 mk addpatchinfo
# 2003-11-01 mk VIEW pg_patchinfo
# 2004-11-04 mk renamed VIEW to pg_patches;
# features selectable via command line (-F)
# 2004-12-14 mk freeze
#-----------------------------------------------------------------------
ALLFEATURES="22 27"
#-----------------------------------------------------------------------
abortscript(){
echo 1>&2
echo "$1" 1>&2
exit 1
}
setconnectable(){
db=$1
allow=$2
$CMD template1 >/dev/null <<EOF
UPDATE pg_database SET datallowconn = $allow WHERE datname = '$db';
EOF
}
freeze(){
db=$1
$CMD $db >/dev/null <<EOF
VACUUM FREEZE;
EOF
}
# This does not work for database names with spaces or other funny
# characters.
enumdatabases(){
echo "SELECT datname FROM pg_database;" \
| $CMD template1 \
| sed -e '/1: datname = "/!d' -e 's/.*1: datname = "//' -e 's/".*//'
}
add22indexstat(){
db=$1
echo "adding \"pg_indexstat\", ignore error if it already exists"
$CMD $db >/dev/null <<EOF
CREATE TABLE pg_catalog.pg_indexstat( \
istindex oid NOT NULL, \
istcorrel float4 NOT NULL \
) WITHOUT OIDS;
CREATE UNIQUE INDEX pg_indexstat_index_index \
ON pg_indexstat(istindex);
EOF
}
add27patchinfo(){
db=$1
echo "adding \"pg_patchinfo()\", ignore error if it already exists"
$CMD $db >/dev/null <<EOF
COPY pg_proc FROM stdin WITH OIDS;
2981 pg_patchinfo 11 1 12 f f t t i 0 2249 show_patchinfo - \N
\.
-- copy acl from version()
UPDATE pg_proc SET proacl=(SELECT proacl FROM pg_proc WHERE oid=89) WHERE oid=2981;
CREATE VIEW pg_patches AS SELECT * FROM pg_patchinfo() AS p(name text, version text, base text, descr text);
EOF
}
#-----------------------------------------------------------------------
CMDNAME=`basename $0`
BINDIR="bin"
FEATURES=""
while [ "$#" -gt 0 ]
do
case "$1" in
--username|-U)
POSTGRES_SUPERUSERNAME="$2"
shift;;
--username=*)
POSTGRES_SUPERUSERNAME=`echo $1 | sed 's/^--username=//'`
;;
-U*)
POSTGRES_SUPERUSERNAME=`echo $1 | sed 's/^-U//'`
;;
--feature|-F)
FEATURES="$FEATURES $2"
shift;;
--feature=*)
F=`echo $1 | sed 's/^--feature=//'`
FEATURES="$FEATURES $F"
;;
-F*)
F=`echo $1 | sed 's/^-F//'`
FEATURES="$FEATURES $F"
;;
# Data directory. No default, unless the environment
# variable PGDATA is set.
--pgdata|-D)
PGDATA="$2"
shift;;
--pgdata=*)
PGDATA=`echo $1 | sed 's/^--pgdata=//'`
;;
-D*)
PGDATA=`echo $1 | sed 's/^-D//'`
;;
-*)
echo "$CMDNAME: invalid option: $1"
exit 1
;;
# Non-option argument specifies data directory
*)
PGDATA=$1
;;
esac
shift
done
#-----------------------------------------------------------------------
if [ -z "$PGDATA" ]
then
(
echo "$CMDNAME: no data directory specified"
echo "You must identify the directory where the data for this database system"
echo "resides. Do this with either the invocation option -D or the"
echo "environment variable PGDATA."
) 1>&2
exit 1
fi
#-----------------------------------------------------------------------
PG_OPT="-O"
PG_OPT="$PG_OPT -c search_path=pg_catalog"
PG_OPT="$PG_OPT -c exit_on_error=true"
#PG_OPT="$PG_OPT -c enable_indexstat=false"
PG_OPT="$PG_OPT -D $PGDATA"
CMD="$BINDIR/postgres $PG_OPT"
: ${FEATURES:=$ALLFEATURES}
# Enable connections to template0
setconnectable template0 true || abortscript "cannot enable connections to template0"
for db in `enumdatabases`
do
echo converting database $db ...
for f in $FEATURES
do
case $f in
22)
add22indexstat $db # || abortscript "cannot convert database $db"
;;
27)
add27patchinfo $db # || abortscript "cannot convert database $db"
;;
*)
abortscript "unknown feature $f"
;;
esac
done
freeze $db || abortscript "cannot freeze $db"
done
# Re-disable connections to template0
setconnectable template0 false || abortscript "cannot re-disable connections to template0"