#!/usr/bin/perl
+#
+# PostGIS - Spatial Types for PostgreSQL
+# http://postgis.refractions.net
+#
+# Copyright (C) 2011 OpenGeo.org
+# Copyright (C) 2009-2010 Paul Ramsey <pramsey@opengeo.org>
+# Copyright (C) 2001-2005 Refractions Research Inc.
+#
+# This is free software; you can redistribute and/or modify it under
+# the terms of the GNU General Public Licence. See the COPYING file.
+#
+
+use warnings;
+use strict;
+
eval "exec perl -w $0 $@"
if (0);
my @casts = ();
my @funcs = ();
my @types = ();
+my %type_funcs = ();
+my @type_funcs= (); # function to drop _after_ type drop
my @ops = ();
+my @opcs = ();
+my @views = ();
+my @tables = ();
my $version = $ARGV[1];
print "BEGIN;\n";
-if ( $version ge "73" )
-{
- print "-- Drop index bindings from system tables\n";
- print "DROP OPERATOR CLASS gist_geometry_ops USING gist CASCADE;\n";
-}
-else
+open( INPUT, $ARGV[0] ) || die "Couldn't open file: $ARGV[0]\n";
+
+while( my $line = <INPUT>)
{
- print "-- Drop index bindings from system tables\n";
- print "DELETE FROM pg_amproc WHERE amopclaid = (SELECT oid FROM pg_opclass WHERE opcname = 'gist_geometry_ops');\n";
- print "DELETE FROM pg_amop WHERE amopclaid = (SELECT oid FROM pg_opclass WHERE opcname = 'gist_geometry_ops');\n";
- print "DELETE FROM pg_opclass WHERE opcname = 'gist_geometry_ops';\n";
+ if ($line =~ /^create function/i) {
+ push (@funcs, $line);
+ }
+ elsif ($line =~ /^create or replace view\s*(\w+)/i) {
+ push (@views, $1);
+ }
+ elsif ($line =~ /^create table \s*(\w+)/i) {
+ push (@tables, $1);
+ }
+ elsif ($line =~ /^create or replace function/i) {
+ push (@funcs, $line);
+ }
+ elsif ( $line =~ /^create operator class (\w+)/i ) {
+ my $opcname = $1;
+ my $am = '';
+ while( not $line =~ /;\s*$/ ) {
+ if ( $line =~ /( USING (\w+))/ ) {
+ $am = $1;
+ last;
+ }
+ $line .= <INPUT>;
+ }
+ if ( $am eq '' ) {
+ die "Couldn't parse CREATE OPERATOR CLASS $opcname\n";
+ } else {
+ $opcname .= $am;
+ }
+ push (@opcs, $opcname)
+ }
+ elsif ($line =~ /^create operator.*\(/i) {
+ my $defn = $line;
+ while( not $defn =~ /;\s*$/ ) {
+ $defn .= <INPUT>;
+ }
+ push (@ops, $defn)
+ }
+ elsif ($line =~ /^create aggregate/i) {
+ my $defn = $line;
+ while( not $defn =~ /;\s*$/ ) {
+ $defn .= <INPUT>;
+ }
+ push (@aggs, $defn)
+ }
+ elsif ($line =~ /^create type (\w+)/i) {
+ push (@types, $1);
+ while( not $line =~ /;\s*$/ ) {
+ $line = <INPUT>;
+ if ( $line =~ /(input|output|send|receive|typmod_in|typmod_out|analyze)\s*=\s*(\w+)/ ) {
+ my $role = ${1};
+ my $fname = ${2};
+ $type_funcs{$fname} = $role;
+ }
+ }
+ }
+ elsif ($line =~ /^create cast/i) {
+ push (@casts, $line)
+ }
}
+close( INPUT );
-open( INPUT, $ARGV[0] ) || die "Couldn't open file: $ARGV[0]\n";
+print "-- Drop all views.\n";
+foreach my $view (@views)
+{
+ print "DROP VIEW $view;\n";
+}
-while( my $line = <INPUT>)
+print "-- Drop all tables.\n";
+foreach my $table (@tables)
{
- $line =~ s/[\r\n]//g;
- push (@funcs, $line) if ($line =~ /^create function/i);
- push (@funcs, $line) if ($line =~ /^create or replace function/i);
- push (@ops, $line) if ($line =~ /^create operator.*\(/i);
- push (@aggs, $line) if ($line =~ /^create aggregate/i);
- push (@types, $line) if ($line =~ /^create type/i);
- push (@casts, $line) if ($line =~ /^create cast/i);
+ print "DROP TABLE $table;\n";
}
-close( INPUT );
print "-- Drop all aggregates.\n";
-
foreach my $agg (@aggs)
{
- if ( $agg =~ /create aggregate\s*(\w+)\s*\(/i )
+ if ( $agg =~ /create aggregate\s*(\w+)\s*\(\s*.*basetype = (\w+)/ism )
{
- if ( $version eq "71" )
- {
- print "DROP AGGREGATE $1 geometry;\n";
- }
- else
- {
- print "DROP AGGREGATE $1 ( geometry );\n";
- }
+ print "DROP AGGREGATE $1 ($2);\n";
}
else
{
}
}
-print "-- Drop all operators.\n";
+print "-- Drop all operators classes and families.\n";
+foreach my $opc (@opcs)
+{
+ print "DROP OPERATOR CLASS $opc;\n";
+ print "DROP OPERATOR FAMILY $opc;\n";
+}
+print "-- Drop all operators.\n";
foreach my $op (@ops)
{
- if ($op =~ /create operator ([^(]+)/i )
+ if ($op =~ /create operator ([^(]+)\s*\(.*LEFTARG\s*=\s*(\w+),\s*RIGHTARG\s*=\s*(\w+).*/ism )
{
- if ( $version ge "73" )
- {
- print "DROP OPERATOR $1 (geometry,geometry) CASCADE;\n";
- }
- else
- {
- print "DROP OPERATOR $1 (geometry,geometry);\n";
- }
+ print "DROP OPERATOR $1 ($2,$3) CASCADE;\n";
}
else
{
print "-- Drop all casts.\n";
-
foreach my $cast (@casts)
{
if ($cast =~ /create cast\s*\((.+?)\)/i )
}
}
-print "-- Drop all functions.\n";
+print "-- Drop all functions except " . (keys %type_funcs) . " needed for type definition.\n";
foreach my $fn (@funcs)
{
my $fn_nm = $1;
my $fn_arg = $2;
- if ( $version ge "73" )
+ $fn_arg =~ s/DEFAULT [\w']+//ig;
+
+ if ( ! exists($type_funcs{$fn_nm}) )
{
- if ( ! ( $fn_nm =~ /_in/i || $fn_nm =~ /_out/i || $fn_nm =~ /_recv/i || $fn_nm =~ /_send/i || $fn_nm =~ /_analyze/i ) )
- {
- print "DROP FUNCTION $fn_nm ($fn_arg) CASCADE;\n";
- }
- }
+ print "DROP FUNCTION IF EXISTS $fn_nm ($fn_arg);\n";
+ }
else
{
- print "DROP FUNCTION $fn_nm ($fn_arg);\n";
+ if ( $type_funcs{$fn_nm} =~ /(typmod|analyze)/ ) {
+ push(@type_funcs, $fn);
+ }
}
}
else
}
}
-print "-- Drop all types.\n";
+print "-- Drop all types.\n";
foreach my $type (@types)
{
- if ($type =~ /create type (\w+)/i )
+ print "DROP TYPE $type CASCADE;\n";
+}
+
+print "-- Drop all functions needed for types definition.\n";
+foreach my $fn (@type_funcs)
+{
+ if ($fn =~ /.* function ([^(]+)\((.*)\)/i )
{
- if ( $version ge "73" )
- {
- print "DROP TYPE $1 CASCADE;\n";
- }
- else
- {
- print "DROP TYPE $1;\n";
- }
+ my $fn_nm = $1;
+ my $fn_arg = $2;
+
+ $fn_arg =~ s/DEFAULT [\w']+//ig;
+
+ print "DROP FUNCTION IF EXISTS $fn_nm ($fn_arg);\n";
}
else
{
- die "Couldn't parse line: $type\n";
+ die "Couldn't parse line: $fn\n";
}
}
-print "-- Drop all tables.\n";
-print "DROP TABLE spatial_ref_sys;\n";
-print "DROP TABLE geometry_columns;\n";
print "\n";
print "COMMIT;\n";