mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 16:21:20 +03:00
Have pg_dumpall write CREATE USER and CREATE GROUP commands instead of raw
COPYs of pg_shadow and pg_group. It also turns out that pg_dumpall was all but broken for multiple servers running at non-standard port numbers. You might get the users and groups from one server and the databases from another. Fixed that. A little user interface and code cleanup along with that. This also takes care of the portability bug discussed in "[BUGS] pg_dumpall" in March 2000.
This commit is contained in:
parent
d66a8c7c47
commit
51afb9305c
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 1994, Regents of the University of California
|
# Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.16 2000/06/28 18:29:16 petere Exp $
|
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.17 2000/07/03 16:35:39 petere Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -17,11 +17,17 @@ OBJS= pg_dump.o common.o $(STRDUP)
|
|||||||
CFLAGS+= -I$(LIBPQDIR)
|
CFLAGS+= -I$(LIBPQDIR)
|
||||||
|
|
||||||
|
|
||||||
all: submake pg_dump$(X)
|
all: submake pg_dump pg_dumpall
|
||||||
|
|
||||||
pg_dump$(X): $(OBJS) $(LIBPQDIR)/libpq.a
|
pg_dump: $(OBJS) $(LIBPQDIR)/libpq.a
|
||||||
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ) $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPQ) $(LDFLAGS)
|
||||||
|
|
||||||
|
pg_dumpall: pg_dumpall.sh
|
||||||
|
sed -e 's:__VERSION__:$(VERSION):g' \
|
||||||
|
-e 's:__MULTIBYTE__:$(MULTIBYTE):g' \
|
||||||
|
-e 's:__bindir__:$(bindir):g' \
|
||||||
|
< $< > $@
|
||||||
|
|
||||||
../../utils/strdup.o:
|
../../utils/strdup.o:
|
||||||
$(MAKE) -C ../../utils strdup.o
|
$(MAKE) -C ../../utils strdup.o
|
||||||
|
|
||||||
@ -44,7 +50,7 @@ depend dep:
|
|||||||
$(CC) -MM $(CFLAGS) *.c >depend
|
$(CC) -MM $(CFLAGS) *.c >depend
|
||||||
|
|
||||||
clean distclean maintainer-clean:
|
clean distclean maintainer-clean:
|
||||||
rm -f pg_dump$(X) $(OBJS)
|
rm -f pg_dump$(X) $(OBJS) pg_dumpall
|
||||||
|
|
||||||
ifeq (depend,$(wildcard depend))
|
ifeq (depend,$(wildcard depend))
|
||||||
include depend
|
include depend
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# pg_dumpall [pg_dump parameters]
|
|
||||||
# dumps all databases to standard output
|
|
||||||
# It also dumps the pg_shadow and pg_group tables, which belong to the
|
|
||||||
# whole installation rather than any one individual database.
|
|
||||||
#
|
|
||||||
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall,v 1.27 2000/05/25 20:18:15 tgl Exp $
|
|
||||||
#
|
|
||||||
# to adapt to System V vs. BSD 'echo'
|
|
||||||
if echo '\\' | grep '\\\\' >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
BS='\' # BSD
|
|
||||||
else
|
|
||||||
BS='\\' # System V
|
|
||||||
fi
|
|
||||||
#
|
|
||||||
# Dump everyone but the postgres user
|
|
||||||
# initdb creates him
|
|
||||||
#
|
|
||||||
# get the postgres user id
|
|
||||||
#
|
|
||||||
POSTGRES_SUPER_USER_ID="`echo \" \
|
|
||||||
select datdba \
|
|
||||||
from pg_database \
|
|
||||||
where datname = 'template1'; \" | \
|
|
||||||
psql -A -q -t template1`"
|
|
||||||
echo "${BS}connect template1"
|
|
||||||
#
|
|
||||||
# delete all users in case they run this twice
|
|
||||||
#
|
|
||||||
# we don't use POSTGRES_SUPER_USER_ID because the postgres super user id
|
|
||||||
# could be different on the two installations
|
|
||||||
#
|
|
||||||
echo "select datdba into table tmp_pg_shadow \
|
|
||||||
from pg_database where datname = 'template1';"
|
|
||||||
echo "delete from pg_shadow where usesysid <> tmp_pg_shadow.datdba;"
|
|
||||||
echo "drop table tmp_pg_shadow;"
|
|
||||||
#
|
|
||||||
# load all the non-postgres users
|
|
||||||
# XXX this breaks badly if the layout of pg_shadow ever changes.
|
|
||||||
# It'd be better to convert the data into CREATE USER commands.
|
|
||||||
#
|
|
||||||
echo "copy pg_shadow from stdin;"
|
|
||||||
psql -q template1 <<END
|
|
||||||
select pg_shadow.*
|
|
||||||
into table tmp_pg_shadow
|
|
||||||
from pg_shadow
|
|
||||||
where usesysid <> $POSTGRES_SUPER_USER_ID;
|
|
||||||
copy tmp_pg_shadow to stdout;
|
|
||||||
drop table tmp_pg_shadow;
|
|
||||||
END
|
|
||||||
echo "${BS}."
|
|
||||||
#
|
|
||||||
# copy the pg_group table too
|
|
||||||
# XXX this breaks badly if the layout of pg_group ever changes.
|
|
||||||
# It'd be better to convert the data into CREATE GROUP commands.
|
|
||||||
#
|
|
||||||
echo "delete from pg_group;"
|
|
||||||
echo "copy pg_group from stdin;"
|
|
||||||
psql -q template1 <<END
|
|
||||||
copy pg_group to stdout;
|
|
||||||
END
|
|
||||||
echo "${BS}."
|
|
||||||
#
|
|
||||||
# For each database, run pg_dump to dump the contents of that database.
|
|
||||||
#
|
|
||||||
psql -A -q -t -c "select datname,datdba,encoding from pg_database" template1 | grep '|' | tr '|' ' ' | \
|
|
||||||
grep -v '^template1 ' | \
|
|
||||||
while read DATABASE DBUSERID ENCODING
|
|
||||||
do
|
|
||||||
DBUSERNAME="`echo \" \
|
|
||||||
select usename \
|
|
||||||
from pg_user \
|
|
||||||
where usesysid = $DBUSERID; \" | \
|
|
||||||
psql -A -q -t template1`"
|
|
||||||
|
|
||||||
echo "${BS}connect template1 $DBUSERNAME"
|
|
||||||
|
|
||||||
if sh -c "pg_encoding $ENCODING" >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo "create database \"$DATABASE\" with encoding='`pg_encoding $ENCODING`';"
|
|
||||||
else
|
|
||||||
echo "create database \"$DATABASE\";"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "${BS}connect $DATABASE $DBUSERNAME"
|
|
||||||
pg_dump ${1+"$@"} "$DATABASE"
|
|
||||||
if [ "$?" -ne 0 ]
|
|
||||||
then echo "pg_dump failed on $DATABASE, exiting" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
exit 0
|
|
211
src/bin/pg_dump/pg_dumpall.sh
Normal file
211
src/bin/pg_dump/pg_dumpall.sh
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# pg_dumpall
|
||||||
|
#
|
||||||
|
# Dumps all databases to standard output. It also dumps the "pg_shadow"
|
||||||
|
# and "pg_group" tables, which belong to the whole installation rather
|
||||||
|
# than any one individual database.
|
||||||
|
#
|
||||||
|
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.1 2000/07/03 16:35:39 petere Exp $
|
||||||
|
|
||||||
|
CMDNAME=`basename $0`
|
||||||
|
|
||||||
|
# substituted at build
|
||||||
|
VERSION='__VERSION__'
|
||||||
|
MULTIBYTE='__MULTIBYTE__'
|
||||||
|
bindir='__bindir__'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Find out where we're located
|
||||||
|
#
|
||||||
|
PGPATH=
|
||||||
|
if echo "$0" | grep '/' > /dev/null 2>&1 ; then
|
||||||
|
# explicit dir name given
|
||||||
|
PGPATH=`echo $0 | sed 's,/[^/]*$,,'` # (dirname command is not portable)
|
||||||
|
else
|
||||||
|
# look for it in PATH ('which' command is not portable)
|
||||||
|
for dir in `echo "$PATH" | sed 's/:/ /g'` ; do
|
||||||
|
# empty entry in path means current dir
|
||||||
|
[ x"$dir" = x ] && dir='.'
|
||||||
|
if [ -f "$dir/$CMDNAME" ] ; then
|
||||||
|
PGPATH="$dir"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# As last resort use the installation directory. We don't want to use
|
||||||
|
# this as first resort because depending on how users do release upgrades
|
||||||
|
# they might temporarily move the installation tree elsewhere, so we'd
|
||||||
|
# accidentally invoke the newly installed versions of pg_dump and psql.
|
||||||
|
if [ x"$PGPATH" = x"" ]; then
|
||||||
|
PGPATH=$bindir
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Look for needed programs
|
||||||
|
#
|
||||||
|
for prog in pg_dump psql ; do
|
||||||
|
if [ ! -x "$PGPATH/$prog" ] ; then
|
||||||
|
echo "The program $prog needed by $CMDNAME could not be found. It was"
|
||||||
|
echo "expected at:"
|
||||||
|
echo " $PGPATH/$prog"
|
||||||
|
echo "If this is not the correct directory, please start $CMDNAME"
|
||||||
|
echo "with a full search path. Otherwise make sure that the program"
|
||||||
|
echo "was installed successfully."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
#
|
||||||
|
# to adapt to System V vs. BSD 'echo'
|
||||||
|
#
|
||||||
|
if echo '\\' | grep '\\\\' >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
BS='\' dummy='\' # BSD
|
||||||
|
else
|
||||||
|
BS='\\' # System V
|
||||||
|
fi
|
||||||
|
# The dummy assignment is necessary to prevent Emacs' font-lock
|
||||||
|
# mode from going ballistic when editing this file.
|
||||||
|
|
||||||
|
|
||||||
|
usage=
|
||||||
|
cleanschema=
|
||||||
|
|
||||||
|
#
|
||||||
|
# Scan options. We're interested in the -h (host), -p (port), and -c (clean) options.
|
||||||
|
# The rest we pass to pg_dump, which may or may not be useful.
|
||||||
|
#
|
||||||
|
while [ $# -gt 0 ] ; do
|
||||||
|
case $1 in
|
||||||
|
--help)
|
||||||
|
usage=t
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--version)
|
||||||
|
echo "pg_dumpall (PostgreSQL) $VERSION"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--host|-h)
|
||||||
|
connectopts="$connectopts -h $2"
|
||||||
|
shift;;
|
||||||
|
-h*)
|
||||||
|
connectopts="$connectopts $1"
|
||||||
|
;;
|
||||||
|
--host=*)
|
||||||
|
connectopts="$connectopts -h "`echo $1 | sed 's/^--host=//'`
|
||||||
|
;;
|
||||||
|
--port|-p)
|
||||||
|
connectopts="$connectopts -p $2"
|
||||||
|
shift;;
|
||||||
|
-p*)
|
||||||
|
connectopts="$connectopts $1"
|
||||||
|
;;
|
||||||
|
--port=*)
|
||||||
|
connectopts="$connectopts -p "`echo $1 | sed 's/^--port=//'`
|
||||||
|
;;
|
||||||
|
-c|--clean)
|
||||||
|
cleanschema=yes
|
||||||
|
pgdumpextraopts="$pgdumpextraopts -c"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
pgdumpextraopts="$pgdumpextraopts $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$usage" ] ; then
|
||||||
|
echo "$CMDNAME dumps a PostgreSQL database cluster."
|
||||||
|
echo
|
||||||
|
echo "Usage:"
|
||||||
|
echo " $CMDNAME [ -c ] [ -h host ] [ -p port ]"
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " -c, --clean clean (drop) schema prior to create"
|
||||||
|
echo " -h, --host <hostname> server host name"
|
||||||
|
echo " -p, --port <port> server port number"
|
||||||
|
echo "Any extra options will be passed to pg_dump."
|
||||||
|
echo
|
||||||
|
echo "Report bugs to <pgsql-bugs@postgresql.org>."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
PSQL="${PGPATH}/psql $connectopts"
|
||||||
|
PGDUMP="${PGPATH}/pg_dump $connectopts $pgdumpextraopts"
|
||||||
|
|
||||||
|
|
||||||
|
echo "--"
|
||||||
|
echo "-- pg_dumpall ($VERSION) $connectopts $pgdumpextraopts"
|
||||||
|
echo "--"
|
||||||
|
echo "${BS}connect template1"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dump users (but not the user created by initdb)
|
||||||
|
#
|
||||||
|
echo "DELETE FROM pg_shadow WHERE usesysid NOT IN (SELECT datdba FROM pg_database WHERE datname = 'template1');"
|
||||||
|
echo
|
||||||
|
|
||||||
|
$PSQL -d template1 -At <<__END__
|
||||||
|
SELECT
|
||||||
|
'CREATE USER "' || usename || '" WITH SYSID ' || usesysid
|
||||||
|
|| CASE WHEN passwd IS NOT NULL THEN ' PASSWORD ''' || passwd || '''' else '' end
|
||||||
|
|| CASE WHEN usecreatedb THEN ' CREATEDB'::text ELSE ' NOCREATEDB' END
|
||||||
|
|| CASE WHEN usesuper THEN ' CREATEUSER'::text ELSE ' NOCREATEUSER' END
|
||||||
|
|| CASE WHEN valuntil IS NOT NULL THEN ' VALID UNTIL '''::text
|
||||||
|
|| CAST(valuntil AS TIMESTAMP) || '''' ELSE '' END || ';'
|
||||||
|
FROM pg_shadow
|
||||||
|
WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1');
|
||||||
|
__END__
|
||||||
|
echo
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dump groups
|
||||||
|
#
|
||||||
|
echo "DELETE FROM pg_group;"
|
||||||
|
echo
|
||||||
|
|
||||||
|
$PSQL -d template1 -At -F ' ' -c 'SELECT * FROM pg_group;' | \
|
||||||
|
while read GRONAME GROSYSID GROLIST ; do
|
||||||
|
echo "CREATE GROUP \"$GRONAME\" WITH SYSID ${GROSYSID};"
|
||||||
|
raw_grolist=`echo "$GROLIST" | sed 's/^{\(.*\)}$/\1/' | tr ',' ' '`
|
||||||
|
for userid in $raw_grolist ; do
|
||||||
|
username=`$PSQL -d template1 -At -c "SELECT usename FROM pg_shadow WHERE usesysid = ${userid};"`
|
||||||
|
echo " ALTER GROUP \"$GRONAME\" ADD USER \"$username\";"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# For each database, run pg_dump to dump the contents of that database.
|
||||||
|
|
||||||
|
$PSQL -d template1 -At -F ' ' \
|
||||||
|
-c "SELECT d.datname, u.usename, pg_encoding_to_char(d.encoding) FROM pg_database d, pg_shadow u WHERE d.datdba = u.usesysid AND datname <> 'template1';" | \
|
||||||
|
while read DATABASE DBOWNER ENCODING ; do
|
||||||
|
echo
|
||||||
|
echo "--"
|
||||||
|
echo "-- Database $DATABASE"
|
||||||
|
echo "--"
|
||||||
|
echo "${BS}connect template1 $DBOWNER"
|
||||||
|
|
||||||
|
if [ "$cleanschema" = yes ] ; then
|
||||||
|
echo "DROP DATABASE \"$DATABASE\";"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$MULTIBYTE" != x"" ] ; then
|
||||||
|
echo "CREATE DATABASE \"$DATABASE\" WITH ENCODING = '$ENCODING';"
|
||||||
|
else
|
||||||
|
echo "CREATE DATABASE \"$DATABASE\";"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${BS}connect $DATABASE $DBOWNER"
|
||||||
|
$PGDUMP -d "$DATABASE"
|
||||||
|
if [ "$?" -ne 0 ] ; then
|
||||||
|
echo "pg_dump failed on $DATABASE, exiting" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
Loading…
x
Reference in New Issue
Block a user