File: postgis_restore.pl.in

package info (click to toggle)
postgis 3.5.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 69,528 kB
  • sloc: ansic: 162,229; sql: 93,970; xml: 53,139; cpp: 12,646; perl: 5,658; sh: 5,369; makefile: 3,435; python: 1,205; yacc: 447; lex: 151; pascal: 58
file content (827 lines) | stat: -rw-r--r-- 24,696 bytes parent folder | download | duplicates (2)
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
#!/usr/bin/perl

#
# PostGIS - Spatial Types for PostgreSQL
# http://postgis.net
#
# Copyright (C) 2004-2023 Sandro Santilli <strk@kbt.io>
# Copyright (C) 2011 OpenGeo.org
# Copyright (C) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
#
# This is free software; you can redistribute and/or modify it under
# the terms of the GNU General Public Licence. See the COPYING file.
#
#---------------------------------------------------------------------
#
# This script is aimed at restoring postgis data
# from a dumpfile produced by pg_dump -Fc
#
# Basically it will restore all but things known to belong
# to postgis. Will also convert some old known constructs
# into new ones.
#
# Tested on:
#
#    pg-12/pgis-2.5.9 => pg-12/pgis-3.5.0dev
#    pg-8.4.9/pgis-1.4.3    => pg-8.4.9/pgis-2.0.0SVN
#    pg-8.4.9/pgis-2.0.0SVN => pg-8.4.9/pgis-2.0.0SVN
#    pg-8.4.9/pgis-2.0.0SVN => pg-9.1.2/pgis-2.0.0SVN
#    pg-9.1b3/pgis-1.5.3    => pg-9.1.1/pgis-2.0.0SVN
#
#---------------------------------------------------------------------

use warnings;
use strict;

my $me = $0;

my $usage = qq{
Usage:	$me [-v] [-L TOC] [-s schema] <dumpfile>
        Restore a custom dump (pg_dump -Fc) of a PostGIS-enabled database.
        First dump the old database: pg_dump -Fc MYDB > MYDB.dmp
        Then create a new database: createdb NEWDB
        Then install PostGIS in the new database:
           psql -f postgis/postgis.sql NEWDB
        Also install PostGIS topology and raster, if you were using them:
           psql -f topology/topology.sql NEWDB
           psql -f raster/rtpostgis.sql NEWDB
        Finally, pass the dump to this script and feed output to psql:
           $me MYDB.dmp | psql NEWDB
        The -v switch writes detailed report on stderr.
        Use -L to provide a TOC rather than extracting it from the dump.
        Use -s if you installed PostGIS in a custom schema.

};

my $DEBUG = 0;
my $POSTGIS_SCHEMA;
my $POSTGIS_TOC;

# NOTE: the SRID limits here are being discussed:
# http://lists.osgeo.org/pipermail/postgis-devel/2012-February/018440.html
my $SRID_MAXIMUM = @SRID_MAXIMUM@;
my $SRID_USER_MAXIMUM = @SRID_USER_MAXIMUM@;

while (@ARGV && $ARGV[0] =~ /^-/) {
  my $arg = shift(@ARGV);
  if ( $arg eq '-v' ) {
    $DEBUG = 1;
  }
  elsif ( $arg eq '-s' ) {
    $POSTGIS_SCHEMA = shift(@ARGV);
  }
  elsif ( $arg eq '-L' ) {
    $POSTGIS_TOC = shift(@ARGV);
  }
  elsif ( $arg eq '--' ) {
    last;
  }
  else {
    print STDERR "Unknown switch " . $arg;
    die $usage;
  }
}

die $usage if (@ARGV < 1);

my $dumpfile = $ARGV[0];
my $manifest = $dumpfile;
$manifest =~ s/\/$//; # strip trailing slash
$manifest .= ".lst";
my $hasTopology = 0;

die "$me:\tUnable to find 'pg_dump' on the path.\n" if ! `pg_dump --version`;
die "$me:\tUnable to find 'pg_restore' on the path.\n" if ! `pg_restore --version`;
die "$me:\tUnable to open dump file '$dumpfile'.\n" if ! -r $dumpfile;

print STDERR "Converting $dumpfile to ASCII on stdout...\n"
  if $DEBUG;

STDOUT->autoflush(1);

######################################################################
# Load the signatures of things to skip.
#

print STDERR "  Reading list of functions to ignore...\n"
  if $DEBUG;

my %skip = ();
while(my $l = <DATA>) {
  chop($l);
  print STDERR "DATA: $l\n" if $DEBUG;
  $l =~ s/\s//g;
  $skip{$l} = 1;
}

######################################################################
# Write a new manifest for the dump file, skipping the things that
# are part of PostGIS
#

if(!defined($POSTGIS_TOC)) {
  print STDERR "  Writing manifest of things to read from dump file...\n"
    if $DEBUG;

  open( DUMP, "pg_restore -f - -l $dumpfile |" ) || die "$me:\tCannot open dump file '$dumpfile'\n";
} else {
  open( DUMP, '<' . $POSTGIS_TOC) || die "$me:\tCannot open TOC file '$POSTGIS_TOC'\n";
}
open( MANIFEST, ">$manifest" ) || die "$me:\tCannot open manifest file '$manifest'\n";
while( my $l = <DUMP> ) {

  next if $l =~ /^\;/;
  my $sigHR = linesignature($l);
  next unless length($sigHR);
  my $sig = $sigHR;
  # always skip associated comments associated to objects,
  # see https://trac.osgeo.org/postgis/ticket/3078
  $sig =~ s/^COMMENT//g;
  # always skip shelltype when type is skipped
  # see https://trac.osgeo.org/postgis/ticket/5569#comment:16
  $sig =~ s/^SHELLTYPE/TYPE/g;
  $sig =~ s/\s//g;
  $hasTopology = 1 if $sig eq 'SCHEMAtopology';

	if ( not defined ($POSTGIS_SCHEMA) )
	{
		if ( $l =~ / TABLE DATA ([^ ]*) spatial_ref_sys / )
		{
			$POSTGIS_SCHEMA = $1;
			print STDERR "  Setting postgis schema to $POSTGIS_SCHEMA, as found in the dump\n"
			  if $DEBUG;
		}
	}

  if ( $skip{$sig} ) {
    print STDERR "SKIP: $sigHR\n" if $DEBUG;
    next
  }
  print STDERR "KEEP: $sigHR\n" if $DEBUG;
  print MANIFEST $l;

}
close(MANIFEST);
close(DUMP) || die "$me: pg_restore returned an error\n";

######################################################################
# Convert the dump file into an ASCII file, stripping out the
# unwanted bits.
#
print STDERR "  Writing ASCII to stdout...\n"
  if $DEBUG;
open( INPUT, "pg_restore -f - -L $manifest $dumpfile |") || die "$me:\tCan't run pg_restore\n";

if ( defined $POSTGIS_SCHEMA ) {
  print STDOUT "SET search_path = \"" . $POSTGIS_SCHEMA . "\";\n";
}

#
# Disable topology metadata tables triggers to allow for population
# in arbitrary order.
#
if ( $hasTopology ) {
  print STDOUT "ALTER TABLE topology.layer DISABLE TRIGGER ALL;\n";
}

# Drop the spatial_ref_sys_srid_check to allow for custom invalid SRIDs in the dump
print STDOUT "ALTER TABLE spatial_ref_sys DROP constraint "
           . "spatial_ref_sys_srid_check;\n";
# Drop the spatial_ref_sys primary key to allow for SRID conversions
# which possibly end up taking the same spot
print STDOUT "ALTER TABLE spatial_ref_sys DROP constraint "
           . "spatial_ref_sys_pkey;\n";

# Backup entries found in new spatial_ref_sys for later updating the
print STDOUT "CREATE TEMP TABLE _pgis_restore_spatial_ref_sys AS "
            ."SELECT * FROM spatial_ref_sys;\n";
print STDOUT "DELETE FROM spatial_ref_sys;\n";

my $inCopy;
while( my $l = <INPUT> ) {
  if ( $l =~ /^COPY .+ FROM stdin;$/ ) {
    $inCopy = 1;
  }
  elsif ( $inCopy && $l =~ /^\\\.$/ ) {
    $inCopy = 0;
  }

  next if !$inCopy && $l =~ /^ *--/;

  if ( $l =~ /^SET search_path/ ) {
    $l =~ s/; *$/, public;/;
  }

  # This is to avoid confusing OPERATOR CLASS and OPERATOR FAMILY
  # with OPERATOR below
  elsif ( $l =~ /CREATE OPERATOR CLASS/ || $l =~ /CREATE OPERATOR FAMILY/ )
  {
  }

  # We can't skip OPERATORS from the manifest file
  # because it doesn't contain enough information
  # about the type the operator is for
  elsif ( $l =~ /CREATE OPERATOR *([^ ,]*)/)
  {
    my $name = canonicalize_typename($1);
    my $larg = undef;
    my $rarg = undef;
    my @sublines = ($l);
    while( my $subline = <INPUT>)
    {
      push(@sublines, $subline);
      last if $subline =~ /;[\t ]*$/;
      if ( $subline =~ /leftarg *= *([^ ,]*)/i )
      {
        $larg=canonicalize_typename($1);
      }
      if ( $subline =~ /rightarg *= *([^ ,]*)/i )
      {
        $rarg=canonicalize_typename($1);
      }
    }

    if ( ! $larg ) {
      print STDERR "No larg, @sublines: [" . @sublines . "]\n";
    }

    my $sigHR = "OPERATOR " . $name .' ('.$larg.', '.$rarg.')';
    my $sig = $sigHR; $sig =~ s/\s//g;

    if ( $skip{$sig} )
    {
       print STDERR "SKIP: $sig\n" if $DEBUG;
       next;
    }

    print STDERR "KEEP: $sig\n" if $DEBUG;
    print STDOUT @sublines;
    next;
  }

  # Rewrite spatial table constraints
  #
  # Example 1:
  # CREATE TABLE geos_in (
  #     id integer NOT NULL,
  #     g public.geometry,
  #     CONSTRAINT enforce_dims_g CHECK ((public.st_ndims(g) = 2)),
  #     CONSTRAINT enforce_geotype_g CHECK (((public.geometrytype(g) = 'MULTILINESTRING'::text) OR (g IS NULL))),
  #     CONSTRAINT enforce_srid_g CHECK ((public.st_srid(g) = (-1)))
  # );
  #
  # Example 2:
  # CREATE TABLE boszip (
  #     gid integer NOT NULL,
  #     zip5 character(5),
  #     the_geom geometry,
  #     CONSTRAINT enforce_dims_the_geom CHECK ((ndims(the_geom) = 2)),
  #     CONSTRAINT enforce_geotype_the_geom CHECK (((geometrytype(the_geom) = 'MULTIPOLYGON'::text) OR (the_geom IS NULL))),
  #     CONSTRAINT enforce_srid_the_geom CHECK ((srid(the_geom) = 2249))
  # );
  #
  # Example 3:
  # CREATE TABLE "PIANIFICAZIONE__ELEMENTO_LINEA" (
  #     soft_gis_serial integer NOT NULL,
  #     "G" public.geometry,
  #     CONSTRAINT "enforce_dims_G" CHECK ((public.st_ndims("G") = 2)),
  #     CONSTRAINT "enforce_geotype_G" CHECK (((public.geometrytype("G") = 'MULTICURVE'::text) OR ("G" IS NULL))),
  #     CONSTRAINT "enforce_srid_G" CHECK ((public.st_srid("G") = (-1)))
  # );
  #
  #
  elsif ( $l =~ /CREATE TABLE *([^ ,]*)/)
  {
    print STDOUT $l;
    while( my $subline = <INPUT>)
    {
      if ( $subline =~ /CONSTRAINT "?enforce_dims_/i ) {
        $subline =~ s/\bndims\(/st_ndims(/;
      }
      if ( $subline =~ /CONSTRAINT "?enforce_srid_/i ) {
        $subline =~ s/\bsrid\(/st_srid(/;
        if ( $subline =~ /=\s\(?([-0-9][0-9]*)\)/ ) {
          my $oldsrid = $1;
          my $newsrid = clamp_srid($oldsrid);
          $subline =~ s/=\s*(\(?)[-0-9][0-9]*/= $1$newsrid/;
        } else {
          print STDERR "WARNING: could not find SRID value in: $subline";
        }
      }
      print STDOUT $subline;
      last if $subline =~ /;[\t ]*$/;
    }
    next;
  }

  # Parse comments, to avoid skipping quoted comments
  # See http://trac.osgeo.org/postgis/ticket/2759
  elsif ( $l =~ /^COMMENT ON .* IS '(.*)/)
  {
    print STDOUT $l;
    while( my $subline = <INPUT>)
    # A comment ends with an odd number of single quotes and a semicolon
    {
      print STDOUT $subline;
      last if ( $subline !~ /('*)[\t ]*;[\t ]*$/ || length($1) % 2 == 0)
    }
    next;
  }

  # Clamp SRIDS in spatial_ref_sys
  elsif ( $l =~ /COPY spatial_ref_sys /)
  {
    print STDOUT $l;
    while( my $subline = <INPUT>)
    {
      if ( $subline =~ /([0-9]*)\t/ ) {
        my $oldsrid = $1;
          my $newsrid = clamp_srid($oldsrid);
          $subline =~ s/^[0-9]*\t/${newsrid}\t/;
      }
      print STDOUT $subline;
      last if $subline =~ /^\\.$/;
    }
    next;
  }

  print STDOUT $l;

}

if ( defined $POSTGIS_SCHEMA ) {
  print STDOUT "SET search_path = \"" . $POSTGIS_SCHEMA . "\";\n";
}

if ( $hasTopology ) {

  # Re-enable topology.layer table triggers
  print STDOUT "ALTER TABLE topology.layer ENABLE TRIGGER ALL;\n";

  # Update topology SRID from geometry_columns view.
  # This is mainly to fix srids of -1
  # May be worth providing a "populate_topology_topology"
  print STDOUT "UPDATE topology.topology t set srid = g.srid "
             . "FROM geometry_columns g WHERE t.name = g.f_table_schema "
             . "AND g.f_table_name = 'face' and f_geometry_column = 'mbr';\n";

}

# Update spatial_ref_sys with entries found in new table
print STDOUT "UPDATE spatial_ref_sys o set auth_name = n.auth_name, "
           . "auth_srid = n.auth_srid, srtext = n.srtext, "
           . "proj4text = n.proj4text FROM "
           . "_pgis_restore_spatial_ref_sys n WHERE o.srid = n.srid;\n";
# Insert entries only found in new table
print STDOUT "INSERT INTO spatial_ref_sys SELECT * FROM "
           . "_pgis_restore_spatial_ref_sys n WHERE n.srid "
           . "NOT IN ( SELECT srid FROM spatial_ref_sys );\n";
# DROP TABLE _pgis_restore_spatial_ref_sys;
print STDOUT "DROP TABLE _pgis_restore_spatial_ref_sys;\n";

# Try re-enforcing spatial_ref_sys_srid_check, would fail if impossible
# but you'd still have your data
print STDOUT "ALTER TABLE spatial_ref_sys ADD constraint "
           . "spatial_ref_sys_srid_check check "
           . "( srid > 0 and srid < " . ($SRID_USER_MAXIMUM+1) ." ) ;\n";
# Try re-enforcing spatial_ref_sys primary key, would fail if impossible
# but you'd still have your data
print STDOUT "ALTER TABLE spatial_ref_sys ENABLE TRIGGER ALL;\n";
print STDOUT "ALTER TABLE spatial_ref_sys ADD PRIMARY KEY(srid);\n";


print STDERR "Done.\n";

######################################################################
# Strip a dump file manifest line down to the unique elements of
# type and signature.
#
sub linesignature {

  my $line = shift;
  my $sig;

  $line =~ s/\n$//;
  $line =~ s/\r$//;
  $line =~ s/OPERATOR CLASS/OPERATORCLASS/;
  $line =~ s/TABLE DATA/TABLEDATA/;
  $line =~ s/SHELL TYPE/SHELLTYPE/;
  $line =~ s/PROCEDURAL LANGUAGE/PROCEDURALLANGUAGE/;
  $line =~ s/SEQUENCE SET/SEQUENCE_SET/;

  if( $line =~ /^(\d+)\; (\d+) (\d+) FK (\w+) (\w+) (.*) (\w*)/ ) {
    $sig = "FK " . $4 . " " . $6;
  }
  # We strip argument names from function comments
  elsif ( $line =~ /COMMENT \w+ FUNCTION ([^\(]*)\((.*)\)/ )
  {
    my $name = $1;
    my $args = $2;
    my @args = split('\s*,\s*', $args);

    # No inout indicator or out parameters for function signatures
    my @inonly_args = clean_inout_arguments(@args);

    # For *function* signature we are supposed to strip argument names
    my @unnamed_args = strip_argument_names(@inonly_args);

    $sig = "COMMENT FUNCTION $name(" . join(', ', @unnamed_args) . ")";
  }
  elsif( $line =~ /^(\d+)\; (\d+) (\d+) (\w+) - (\w+) (.*) (\w*)/ ) {
    $sig = $4 . " " . $5 . " " . $6;
  }
  elsif( $line =~ /^(\d+)\; (\d+) (\d+) (\w+) (\w+) (.*) (\w*)/ ) {
    $sig = $4 . " " . $6;
  }
  elsif( $line =~ /PROCEDURALLANGUAGE.*plpgsql/ ) {
    $sig = "PROCEDURAL LANGUAGE plpgsql";
  }
  elsif ( $line =~ /SCHEMA - (\w+)/ ) {
    $sig = "SCHEMA $1";
  }
  elsif ( $line =~ /SEQUENCE - (\w+)/ ) {
    $sig = "SEQUENCE $1";
  }
  else {
    # TODO: something smarter here...
    $sig = $line
  }

  # Strip schema from signature
  # TODO: restrict to POSTGIS_SCHEMA
  $sig =~ s/[^\.(, ]*\.//g;

  return $sig;

}

#
# Canonicalize type names (they change between dump versions).
# Here we also strip schema qualification
#
sub
canonicalize_typename
{
	my $arg=shift;

	# Lower case
	$arg = lc($arg);

	# Trim whitespaces
	$arg =~ s/^\s*//;
	$arg =~ s/\s*$//;

	# Strip schema qualification
	#$arg =~ s/^public.//;
	$arg =~ s/^.*\.//;

	# Handle type name changes
	if ( $arg eq 'opaque' ) {
		$arg = 'internal';
	} elsif ( $arg eq 'boolean' ) {
		$arg = 'bool';
	} elsif ( $arg eq 'oldgeometry' ) {
		$arg = 'geometry';
	}

	# Timestamp with or without time zone
	if ( $arg =~ /timestamp .* time zone/ ) {
		$arg = 'timestamp';
	}

	return $arg;
}

# Change SRID to be within allowed ranges
sub
clamp_srid
{
  my $oldsrid = shift;
  my $newsrid = $oldsrid;

  if ( $oldsrid < 0 ) {
    $newsrid = 0;
    printf STDERR "  WARNING: SRID $oldsrid converted to $newsrid (official UNKNOWN)\n";
  } elsif ( $oldsrid > $SRID_MAXIMUM ) {
    $newsrid = $SRID_USER_MAXIMUM + 1 +
      # -1 is to reduce likelihood of clashes
      # NOTE: must match core implementation (lwutil.c)
      ( $oldsrid % ( $SRID_MAXIMUM - $SRID_USER_MAXIMUM - 1 ) );
    printf STDERR "  WARNING: SRID $oldsrid converted to $newsrid (in reserved zone)\n";
  } elsif ( $oldsrid > $SRID_USER_MAXIMUM ) {
    printf STDERR "  WARNING: SRID $newsrid is in reserved zone\n";
  }

  return $newsrid;
}

# Example:
#  INPUT: inout first double precision, second integer, OUT third text, fourth bool
# OUTPUT: first double precision, second integer, fourth bool
sub clean_inout_arguments {
	my @args = @_;
	my @out;
	#print STDERR "DEBUG: to inout strip: " . join(',', @args) . "\n";
	foreach ( @args )
	{
		my $a = $_;

		#print "  XXX arg: [$a]\n";
		# If the arg is composed by multiple words
		# check for out and inout indicators
		if ( $a =~ m/([^ ]*) (.*)/ )
		{
			# Skip from the first out parameter onward
			last if $1 eq 'OUT';

			# Hide the inout indicator
			$a = $2 if $1 eq 'INOUT';
		}
		#print "  XXX arg became: $a\n";
		push @out, $a;
	}
	#print STDERR "DEBUG: inout striped: " . join(',', @out) . "\n";
	return @out;
}

# Remove argument names from array of arguments
# Example:
#  INPUT: int,named double precision,named text
# OUTPUT: int,double precision,text
sub strip_argument_names {
	my @args = @_;
  my %reserved_sql_word = (
    'timestamp' => 1,
    'double' => 1,
    'character' => 1
  );
	my @out;
	#print "XXX to strip: " . join(',', @args) . "\n";
	foreach ( @args )
	{
		my $a = $_;

		#print "  XXX arg: $a\n";
		# Drop all but reserved words from multi-word arg
		while ( $a =~ m/^([^ ]*) (.*)/ )
		{
			last if $reserved_sql_word{$1};
			$a = $2;
			#print "  XXX arg became: $a\n";
		}
		push @out, $a;
	}
	#print "XXX striped: " . join(',', @out) . "\n";
	return @out;
}


######################################################################
# Here are all the signatures we want to skip but we cannot derive
# from current source
#
__END__
ACL SCHEMA topology
ACL TABLE geography_columns
ACL TABLE geometry_columns
ACL TABLE layer
ACL TABLE raster_columns
ACL TABLE raster_overviews
ACL TABLE spatial_ref_sys
ACL TABLE topology
CAST (box2d AS box3d)
CAST (box2d AS geometry)
CAST (box3d AS box)
CAST (box3d AS box2d)
CAST (box3d AS geometry)
CAST (bytea AS geography)
CAST (bytea AS geometry)
CAST CAST (box2d AS box3d)
CAST CAST (box2d AS geometry)
CAST CAST (box3d AS box)
CAST CAST (box3d AS box2d)
CAST CAST (box3d AS geometry)
CAST CAST (bytea AS geography)
CAST CAST (bytea AS geometry)
CAST CAST (geography AS bytea)
CAST CAST (geography AS geography)
CAST CAST (geography AS geometry)
CAST CAST (geometry AS box)
CAST CAST (geometry AS box2d)
CAST CAST (geometry AS box3d)
CAST CAST (geometry AS bytea)
CAST CAST (geometry AS geography)
CAST CAST (geometry AS geometry)
CAST CAST (geometry AS json)
CAST CAST (geometry AS jsonb)
CAST CAST (geometry AS path)
CAST CAST (geometry AS point)
CAST CAST (geometry AS polygon)
CAST CAST (geometry AS text)
CAST CAST (path AS geometry)
CAST CAST (point AS geometry)
CAST CAST (polygon AS geometry)
CAST CAST (raster AS box3d)
CAST CAST (raster AS bytea)
CAST CAST (raster AS geometry)
CAST CAST (text AS geometry)
CAST CAST (topogeometry AS geometry)
CAST CAST (topogeometry AS integer[])
CAST (geography AS bytea)
CAST (geography AS geography)
CAST (geography AS geometry)
CAST (geometry AS box)
CAST (geometry AS box2d)
CAST (geometry AS box3d)
CAST (geometry AS bytea)
CAST (geometry AS geography)
CAST (geometry AS geometry)
CAST (geometry AS json)
CAST (geometry AS jsonb)
CAST (geometry AS path)
CAST (geometry AS point)
CAST (geometry AS polygon)
CAST (geometry AS text)
CAST (path AS geometry)
CAST (point AS geometry)
CAST (polygon AS geometry)
CAST (text AS geometry)
CONSTRAINT layer layer_pkey
CONSTRAINT layer layer_schema_name_table_name_feature_column_key
CONSTRAINT spatial_ref_sys spatial_ref_sys_pkey
CONSTRAINT topology topology_name_key
CONSTRAINT topology topology_pkey
DEFAULT topology id
DOMAIN topoelement
DOMAIN topoelementarray
FK CONSTRAINT layer layer_topology_id_fkey
FUNCTION jsonb(geometry)
FUNCTION json(geometry)
FUNCTION lockrow(text, text, text, text, timestamp without time zone)
FUNCTION lockrow(text, text, text, timestamp without time zone)
FUNCTION _st_aspect4ma(double precision[], integer[], text[])
FUNCTION st_concavehull(geometry, double precision, boolean)
FUNCTION _st_convertarray4ma(double precision[])
FUNCTION st_distinct4ma(double precision[], integer[], text[])
FUNCTION st_distinct4ma(double precision[], text, text[])
FUNCTION _st_grayscale4ma(double precision[], integer[], text[])
FUNCTION _st_hillshade4ma(double precision[], integer[], text[])
FUNCTION st_invdistweight4ma(double precision[], integer[], text[])
FUNCTION _st_mapalgebra(rastbandarg[], regprocedure, text, integer, integer, text, raster, double precision[], boolean, text[])
FUNCTION st_mapalgebra(raster, integer, regprocedure, double precision[], boolean, text, text, raster, text[])
FUNCTION st_max4ma(double precision[], integer[], text[])
FUNCTION st_max4ma(double precision[], text, text[])
FUNCTION st_mean4ma(double precision[], integer[], text[])
FUNCTION st_mean4ma(double precision[], text, text[])
FUNCTION st_min4ma(double precision[], integer[], text[])
FUNCTION st_min4ma(double precision[], text, text[])
FUNCTION st_mindist4ma(double precision[], integer[], text[])
FUNCTION st_range4ma(double precision[], integer[], text[])
FUNCTION st_range4ma(double precision[], text, text[])
FUNCTION st_rastertoworldcoord(raster, integer, integer)
FUNCTION _st_roughness4ma(double precision[], integer[], text[])
FUNCTION st_setvalues(raster, integer, integer, integer, double precision[], boolean[], boolean)
FUNCTION _st_setvalues(raster, integer, integer, integer, double precision[], boolean[], boolean, double precision, boolean)
FUNCTION st_setvalues(raster, integer, integer, integer, double precision[], double precision, boolean)
FUNCTION _st_slope4ma(double precision[], integer[], text[])
FUNCTION st_stddev4ma(double precision[], integer[], text[])
FUNCTION st_stddev4ma(double precision[], text, text[])
FUNCTION st_sum4ma(double precision[], integer[], text[])
FUNCTION st_sum4ma(double precision[], text, text[])
FUNCTION _st_tpi4ma(double precision[], integer[], text[])
FUNCTION _st_tri4ma(double precision[], integer[], text[])
OPERATOR &&
OPERATOR &&&
OPERATOR &/&
OPERATOR &<
OPERATOR &<|
OPERATOR &>
OPERATOR <
OPERATOR <#>
OPERATOR <->
OPERATOR <<
OPERATOR <<->>
OPERATOR <<@
OPERATOR <<|
OPERATOR <=
OPERATOR =
OPERATOR >
OPERATOR >=
OPERATOR >>
OPERATOR @
OPERATOR @>>
OPERATOR @@
OPERATOR |&>
OPERATOR |=|
OPERATOR |>>
OPERATOR ~
OPERATOR ~=
OPERATOR ~==
OPERATOR ~~
OPERATOR ~~=
OPERATOR <>
OPERATOR&&(box2df,box2df)
OPERATOR@(box2df,box2df)
OPERATOR~(box2df,box2df)
OPERATOR&&(box2df,geometry)
OPERATOR@(box2df,geometry)
OPERATOR~(box2df,geometry)
OPERATORCLASS brin_geography_inclusion_ops
OPERATORCLASS brin_geometry_inclusion_ops_2d
OPERATORCLASS brin_geometry_inclusion_ops_3d
OPERATORCLASS brin_geometry_inclusion_ops_4d
OPERATORCLASS btree_geography_ops
OPERATORCLASS btree_geometry_ops
OPERATORCLASS gist_geography_ops
OPERATORCLASS gist_geometry_ops_2d
OPERATORCLASS gist_geometry_ops_nd
OPERATORCLASS hash_geometry_ops
OPERATORCLASS hash_raster_ops
OPERATORCLASS spgist_geography_ops_nd
OPERATORCLASS spgist_geometry_ops_2d
OPERATORCLASS spgist_geometry_ops_3d
OPERATORCLASS spgist_geometry_ops_nd
OPERATOR&&(geography,geography)
OPERATOR<(geography,geography)
OPERATOR<->(geography,geography)
OPERATOR<=(geography,geography)
OPERATOR=(geography,geography)
OPERATOR>(geography,geography)
OPERATOR>=(geography,geography)
OPERATOR&&(geography,gidx)
OPERATOR&&(geometry,box2df)
OPERATOR@(geometry,box2df)
OPERATOR~(geometry,box2df)
OPERATOR&&&(geometry,geometry)
OPERATOR&&(geometry,geometry)
OPERATOR&/&(geometry,geometry)
OPERATOR&<(geometry,geometry)
OPERATOR&<|(geometry,geometry)
OPERATOR&>(geometry,geometry)
OPERATOR<#>(geometry,geometry)
OPERATOR<(geometry,geometry)
OPERATOR<->(geometry,geometry)
OPERATOR<<(geometry,geometry)
OPERATOR<<->>(geometry,geometry)
OPERATOR<<@(geometry,geometry)
OPERATOR<<|(geometry,geometry)
OPERATOR<=(geometry,geometry)
OPERATOR=(geometry,geometry)
OPERATOR>(geometry,geometry)
OPERATOR>=(geometry,geometry)
OPERATOR>>(geometry,geometry)
OPERATOR@(geometry,geometry)
OPERATOR@>>(geometry,geometry)
OPERATOR@@(geometry,geometry)
OPERATOR|&>(geometry,geometry)
OPERATOR|=|(geometry,geometry)
OPERATOR|>>(geometry,geometry)
OPERATOR~(geometry,geometry)
OPERATOR~=(geometry,geometry)
OPERATOR~==(geometry,geometry)
OPERATOR~~(geometry,geometry)
OPERATOR~~=(geometry,geometry)
OPERATOR&&&(geometry,gidx)
OPERATOR&&(gidx,geography)
OPERATOR&&&(gidx,geometry)
OPERATOR&&&(gidx,gidx)
OPERATOR&&(gidx,gidx)
OPERATOR public brin_geography_inclusion_ops
OPERATOR public brin_geometry_inclusion_ops_2d
OPERATOR public brin_geometry_inclusion_ops_3d
OPERATOR public brin_geometry_inclusion_ops_4d
OPERATOR public btree_geography_ops
OPERATOR public btree_geometry_ops
OPERATOR public gist_geography_ops
OPERATOR public gist_geometry_ops_2d
OPERATOR public gist_geometry_ops_nd
OPERATOR public hash_geometry_ops
OPERATOR public hash_raster_ops
OPERATOR public spgist_geography_ops_nd
OPERATOR public spgist_geometry_ops_2d
OPERATOR public spgist_geometry_ops_3d
OPERATOR public spgist_geometry_ops_nd
RULE geometry_columns geometry_columns_delete
RULE geometry_columns geometry_columns_insert
RULE geometry_columns geometry_columns_update
SCHEMA topology
SEQUENCE BY topology topology_id_seq
SEQUENCE topology_id_seq
SEQUENCE topology topology_id_seq
SHELLTYPE box2d
SHELLTYPE box2df
SHELLTYPE box3d
SHELLTYPE geography
SHELLTYPE geometry
SHELLTYPE gidx
SHELLTYPE raster
SHELLTYPE spheroid
TABLEDATA spatial_ref_sys
TABLE layer
TABLE spatial_ref_sys
TABLE topology
TRIGGER layer layer_integrity_checks
VIEW geography_columns
VIEW geometry_columns
VIEW raster_columns
VIEW raster_overviews