aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_upgrade
blob: d9d6187b86bf74e15318dedcad554317bb54e1c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/bin/sh
#
# pg_upgrade: update a database without needing a full dump/reload cycle.
# CAUTION: read the manual page before trying to use this!

# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_upgrade,v 1.12 1999/09/28 16:02:28 momjian Exp $
#
# NOTE: we must be sure to update the version-checking code a few dozen lines
# below for each new PostgreSQL release.

trap "rm -f /tmp/$$" 0 1 2 3 15

if [ "$#" -eq 0 ]
then	echo "Usage:  $0 [-f inputfile] old_data_dir" 1>&2
	exit 1
fi

if [ "X$1" = "X-f" ]
then	INPUT="$2"
	shift 2
	if [ ! -f "$INPUT" ]
	then	echo "$INPUT does not exist" 1>&2
		exit 1
	fi
else	INPUT=""
fi

if [ "$#" -ne 1 ]
then	echo "Usage:  $0 [-f inputfile] old_data_dir" 1>&2
	exit 1
fi

OLDDIR="$1"

# check things

if [ ! -d "./data" ]
then	echo "`basename $0` must be run from the directory containing
the database directory \`data\' (`dirname $PGDATA`.)" 1>&2
	echo "You must have run initdb to create the template1 database." 1>&2
	exit 1
fi

if [ ! -d "./$OLDDIR" ]
then	echo "You must rename your old data directory to $OLDDIR and run initdb." 1>&2
	exit 1
fi

if [ ! -d "./data/base/template1" ]
then	echo "Cannot find database template1 in ./data/base." 1>&2
	echo "Are you running $0 as the postgres superuser?" 1>&2
	exit 1
fi

if [ ! -d "./$OLDDIR/base/template1" ]
then	echo "There is no database template1 in ./$OLDDIR/base." 1>&2
	exit 1
fi

if [ ! -r "./data/PG_VERSION" ]
then	echo "Cannot read ./data/PG_VERSION --- something is wrong." 1>&2
	exit 1
fi

if [ ! -r "./$OLDDIR/PG_VERSION" ]
then	echo "Cannot read ./$OLDDIR/PG_VERSION --- something is wrong." 1>&2
	exit 1
fi

# Get the actual versions seen in the data dirs.
DESTVERSION=`cat ./data/PG_VERSION`
SRCVERSION=`cat ./$OLDDIR/PG_VERSION`

# Check for version compatibility.
# This code will need to be updated/reviewed for each new PostgreSQL release.

# MYVERSION is the expected output database version
MYVERSION="6.6"

if [ "$DESTVERSION" != "$MYVERSION" ]
then	echo "$0 is for PostgreSQL version $MYVERSION, but ./data/PG_VERSION contains $DESTVERSION." 1>&2
	echo "Did you run initdb for version $MYVERSION?" 1>&2
	exit 1
fi

# Check that input database is of a compatible version (anything with the same
# physical layout of user tables and indexes should be OK).  I did not write
# something like "$SRCVERSION -ge $MINVERSION" because test(1) isn't bright
# enough to compare dotted version strings properly.  Using a case statement
# looks uglier but is more flexible.

case "$SRCVERSION" in
    6.5) ;;
    6.6) ;;
    *)	echo "Sorry, `basename $0` cannot upgrade database version $SRCVERSION to $DESTVERSION." 1>&2
	echo "The on-disk structure of tables has changed." 1>&2
	echo "You will need to dump and restore using pg_dump." 1>&2
	exit 1;;
esac


# OK, ready to proceed.
# XXX Do I need to create a database?

# remove any COPY statements, except for the one that loads pg_shadow.
# there shouldn't be any others in there anyway...

cat $INPUT | awk '	{
				if (toupper($1) == "COPY" && $2 != "pg_shadow")
					while (getline $0 > 0 && $0 != "\\.")
						;
				else	print $0;
			}' >/tmp/$$

# Add a VACUUM command to the end of the pg_dump script.  With MVCC,
# this is necessary to ensure that all the rows in the new database's
# system tables will still be considered committed after we overwrite
# pg_log with the old database's commit log...

echo "VACUUM;" >>/tmp/$$

# Create and vacuum empty tables/indexes

psql "template1" <"/tmp/$$"

if [ $? -ne 0 ]
then	echo "There were errors in the input script $INPUT.
$0 aborted." 1>&2
	exit 1
fi

echo "Input script $INPUT complete, moving data files..."

for DIR in data/base/*
do
	BASEDIR="`basename $DIR`"
	if [ -d "$DIR" -a \
	     -d "$OLDDIR/base/$BASEDIR" -a \( "$BASEDIR" != "template1" \) ]
	then	for FILE in $OLDDIR/base/$BASEDIR/*
		do
			BASEFILE="`basename $FILE`"
			if [ `expr "$BASEFILE" : "pg_"` -ne 3 -a \
				"$BASEFILE" != "PG_VERSION" ]
			then	mv -f $FILE $DIR
			fi
		done
	fi
done

mv -f $OLDDIR/pg_log data
mv -f $OLDDIR/pg_variable data

echo "You must stop/start the postmaster before doing anything else."
echo "You may remove the $OLDDIR directory with 'rm -r $OLDDIR'."
exit 0