33# pg_upgrade: update a database without needing a full dump/reload cycle.
44# CAUTION: read the manual page before trying to use this!
55
6- # $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_upgrade,v 1.17 2001/08/25 18:52:42 tgl Exp $
6+ # $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_upgrade,v 1.18 2002/01/09 16:00:46 momjian Exp $
77#
88# NOTE: we must be sure to update the version-checking code a few dozen lines
99# below for each new PostgreSQL release.
@@ -49,13 +49,13 @@ thenecho "You must rename your old data directory to $OLDDIR and run initdb." 1
4949exit 1
5050fi
5151
52- if [! -d " ./data/base/template1 " ]
52+ if [! -d " ./data/base/1 " ]
5353then echo " Cannot find database template1 in ./data/base." 1>&2
5454echo " Are you running$0 as the postgres superuser?" 1>&2
5555exit 1
5656fi
5757
58- if [! -d " ./$OLDDIR /base/template1 " ]
58+ if [! -d " ./$OLDDIR /base/1 " ]
5959then echo " There is no database template1 in ./$OLDDIR /base." 1>&2
6060exit 1
6161fi
@@ -78,9 +78,9 @@ SRCVERSION=`cat ./$OLDDIR/PG_VERSION`
7878# This code will need to be updated/reviewed for each new PostgreSQL release.
7979
8080# MYVERSION is the expected output database version
81- MYVERSION=" 7.0 "
81+ MYVERSION=" 7.1 "
8282
83- if [" $DESTVERSION " != " $MYVERSION " ]
83+ if [" $DESTVERSION " != " $MYVERSION " -a " $DESTVERSION " != " $SRCVERSION " ]
8484then echo " $0 is for PostgreSQL version$MYVERSION , but ./data/PG_VERSION contains$DESTVERSION ." 1>&2
8585echo " Did you run initdb for version$MYVERSION ?" 1>&2
8686exit 1
9393# looks uglier but is more flexible.
9494
9595case " $SRCVERSION " in
96- # 7.0 ) ;;
96+ # 7.2 ) ;;
9797* )echo " Sorry,` basename$0 ` cannot upgrade database version$SRCVERSION to$DESTVERSION ." 1>&2
9898echo " The on-disk structure of tables has changed." 1>&2
9999echo " You will need to dump and restore using pg_dump." 1>&2
@@ -114,9 +114,9 @@ cat $INPUT | awk '{
114114while (getline $0 > 0 && $0 != "\\.")
115115;
116116elseprint $0;
117- }' > $TMPFILE
117+ }' > $TMPFILE
118118
119- psql" template1" < $TMPFILE
119+ psql" template1" < $TMPFILE
120120
121121if [$? -ne 0 ]
122122then echo " There were errors in the input script$INPUT .
@@ -143,36 +143,94 @@ cat $INPUT | awk 'BEGIN{ print "VACUUM;" }
143143 $2 != "-" &&
144144 $2 != "template1")
145145printf "\\connect %s\nVACUUM;\n", $2;
146- }' > $TMPFILE
146+ }' > $TMPFILE
147147
148- psql" template1" < $TMPFILE
148+ psql" template1" < $TMPFILE
149149
150150if [$? -ne 0 ]
151151then echo " There were errors in the vacuuming step.
152152$0 aborted." 1>&2
153153exit 1
154154fi
155155
156+ # should be pretty small file
157+ pg_dumpall -s> $TMPFILE 2> /dev/null
158+
159+ # flush buffers to disk
160+ pg_ctl stop
161+
156162echo " Commit fixes complete, moving data files..."
157163
158- for DIR in data/base/ *
164+ cat " $INPUT " | while read LINE
159165do
160- BASEDIR=" ` basename$DIR ` "
161- if [-d " $DIR " -a \
162- -d " $OLDDIR /base/$BASEDIR " -a \( " $BASEDIR " != " template1" \) ]
163- then for FILE in $OLDDIR /base/$BASEDIR /*
164- do
165- BASEFILE=" ` basename$FILE ` "
166- if [` expr" $BASEFILE " : " pg_" ` -ne 3-a \
167- " $BASEFILE " != " PG_VERSION" ]
168- then mv -f$FILE $DIR
169- fi
170- done
166+ if /bin/echo" $LINE " | grep -q" ^\\\\ connect"
167+ then OLDDB=" $DB "
168+ DB=" ` /bin/echo\" $LINE \" | cut -d' ' -f2` "
169+ if [" $DB " = " -" ]
170+ then DB=" $OLDDB "
171+ fi
172+ if [" $DB " = " template1" -o " $DB " = " template0" ]
173+ then DB=" "
174+ fi
175+ fi
176+ if echo " $LINE " | grep -q" ^-- TOC Entry ID [0-9]* (OID"
177+ then OID=" ` echo\" $LINE \" | cut -d' ' -f7| tr -d' )' ` "
178+ fi
179+ if echo " $LINE " | grep -q" ^-- Name: [^ ]* Type: TABLE"
180+ then TABLE=" ` echo\" $LINE \" | cut -d' ' -f3` "
181+ # skip system tables
182+ if [" ` echo\" $TABLE \" | cut -c 1-3` " = " pg_" ]
183+ then TABLE=" "
184+ fi
185+ fi
186+ if [" $DB " -a " $OID " -a " $TABLE " ]
187+ then
188+ NEWOID=` awk -F' ' '
189+ BEGIN { newdb=""; newoid="";
190+ newtable=""; ret=0;}
191+ $1 == "\\\\connect" && $2 != "-" {newdb=$2;}
192+ $0 ~ /^-- TOC Entry ID [0-9]* .OID / \
193+ { newoid = substr($7, 1, length($7)-1);}
194+ {print $0 >> "/tmp/x";
195+ print $3 >> "/tmp/x";
196+ print newdb," ", newoid >> "/tmp/x"}
197+ $0 ~ /^-- Name: [^ ]* Type: TABLE / && \
198+ newdb == "' " $DB " ' " && \
199+ $3 == "' " $TABLE " ' " \
200+ { ret=newoid; exit}
201+ END { print ret;}' $TMPFILE `
202+ if [" $NEWOID " -eq 0 ]
203+ then echo " Move of database$DB , OID$OID , table$TABLE failed.\nNew oid not found; exiting" 1>&2
204+ exit 1
205+ fi
206+ # We use stars so we don't have to worry about database oids
207+ if [` ls" $OLDDIR " /base/* /" $OID " | wc -l` -eq 0 ]
208+ then echo " Move of database$DB , OID$OID , table$TABLE failed.\nFile not found; exiting" 1>&2
209+ exit 1
210+ fi
211+ if [` ls" $OLDDIR " /base/* /" $OID " | wc -l` -gt 1 ]
212+ then echo " Move of database$DB , OID$OID , table$TABLE failed.\nToo many found; exiting" 1>&2
213+ exit 1
214+ fi
215+ if [` ls data/base/* /" $NEWOID " | wc -l` -eq 0 ]
216+ then echo " Move of database$DB , OID$OID , table$TABLE to$NEWOID failed.\nFile not found; exiting" 1>&2
217+ exit 1
218+ fi
219+ if [` ls data/base/* /" $NEWOID " | wc -l` -gt 1 ]
220+ then echo " Move of database$DB , OID$OID , table$TABLE to$NEWOID failed.\nToo many found; exiting" 1>&2
221+ exit 1
222+ fi
223+ mv -f" $OLDDIR " /base/* /" $OID " data/base/* /" $NEWOID "
224+ if [" $? " -ne 0 ]
225+ then echo " Move of database$DB , OID$OID , table$TABLE \n to$NEWOID failed.; exiting" 1>&2
226+ exit 1
227+ fi
228+ TABLE=" "
171229fi
172230done
173231
232+ rm -r data/pg_clog
174233mv -f$OLDDIR /pg_clog data
175- mv -f$OLDDIR /pg_variable data
176234
177235echo " You must stop/start the postmaster before doing anything else."
178236echo " You may remove the$OLDDIR directory with 'rm -r$OLDDIR '."