File: create_skip_signatures.pl

package info (click to toggle)
postgis 3.5.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 70,052 kB
  • sloc: ansic: 162,204; sql: 93,950; xml: 53,121; cpp: 12,646; perl: 5,658; sh: 5,369; makefile: 3,434; python: 1,205; yacc: 447; lex: 151; pascal: 58
file content (206 lines) | stat: -rw-r--r-- 4,858 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/env perl

#
# PostGIS - Spatial Types for PostgreSQL
# http://postgis.net
#
# Copyright (C) 2023 Sandro Santilli <strk@kbt.io>
#
# 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 generating a list of objects
# signatures used by postgis_restore.pl to decide
# which objects belong to PostGIS
#
#---------------------------------------------------------------------

use warnings;
use strict;

my $me = $0;

my $usage = qq{
Usage:	$me [<sqlfile> ...]
        Reads sql statements from given files or standard input
				and generates a list of signatures from DROP lines.

};

my %reserved_sql_word = (
	'double' => 1,
	'character' => 1
);

# 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 "XXX to 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 this arg if out only
			next if $1 eq 'out';

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

# Example:
#  INPUT: int,named double precision,named text
# OUTPUT: int,double precision,text
sub strip_argument_names {
	my @args = @_;
	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;
}

sub canonicalize_args {
	my @args = @_;
	my @out;
	foreach ( @args )
	{
		my $a = $_;
		$a =~ s/varchar/character varying/g;
		$a =~ s/float8/double precision/g;
		$a =~ s/\bint\b/integer/g;
		$a =~ s/\bint4\b/integer/g;
		$a =~ s/\bint8\b/bigint/g;
		$a =~ s/\bchar\b/character/g;
		$a =~ s/\bbool\b/boolean/g;
		push @out, $a;
	}
	return @out;
}

sub handle_function_signature {
	my $line = shift;

	$line = lc($line);
	$line =~ s/topology\.//g;

	$line =~ m/ *([^\( ]*) *\((.*)\)/ or die "Unexpected FUNCTION signature: $line";

	my $name = $1;
	my $args = $2;
	$args =~ s/\s*$//; # trim trailing blanks
	$args =~ s/^\s*//; # trim leading blanks

	my @args = split('\s*,\s*', $args);
	@args = canonicalize_args(@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);

	print "FUNCTION $name(" . join(', ', @unnamed_args) . ")\n";
}

while (<>)
{
	#print "XXX 0 $_";

	# type signature
	if ( /^DROP TYPE IF EXISTS\s\s*([^\s]*)/ )
	{
		my $t = lc($1);
		$t =~ s/topology\.//g;
		print "TYPE $t\n";
	}

	# aggregate signature
	if ( /^DROP AGGREGATE IF EXISTS\s+(.*)\((.*)\)/ )
	{
		my $name = lc($1);
		my $args = lc($2);

		s/^\s+//, s/\s+$// for $name;
		$name =~ s/topology\.//g;

		$args =~ s/topology\.//g;
		my @args = split('\s*,\s*', $args);
		@args = canonicalize_args(@args);

		# For *aggregate* signature we are supposed to strip
		# also argument names, which aint easy
		my @unnamed_args = strip_argument_names(@args);

		print "AGGREGATE $name(" . join(', ', @unnamed_args) . ")\n";
	}

	# Function signature
	elsif ( /^DROP FUNCTION IF EXISTS/ )
	{
		my $origline = $_;
		my $line = $origline;

		$line =~ s/DROP FUNCTION IF EXISTS //;

		# We don't want to ALWAYS strip comments
		# because we might handle 'Replaces' comment
		# at some point
		$line =~ s/ *--.*//;

		handle_function_signature($line);
	}

	# Deprecated function signature
	# EXAMPLE: ALTER FUNCTION _st_concavehull( geometry ) RENAME TO _st_concavehull_deprecated_by_postgis_303;
	elsif ( /ALTER FUNCTION .* RENAME TO .*_deprecated_by_postgis_/ )
	{
		my $origline = $_;
		my $line = $origline;

		$line =~ s/ *ALTER FUNCTION (.*) RENAME TO .*_deprecated_by_postgis_.*/$1/;

		handle_function_signature($line);
	}

	# Deprecated function signature using
	# _postgis_drop_function_by_signature
	# EXAMPLE: SELECT _postgis_drop_function_by_signature('pgis_geometry_union_finalfn(internal)');
	elsif ( /SELECT _postgis_drop_function_by_signature\('[^']*'/ )
	{
		my $origline = $_;
		my $line = $origline;

		$line =~ s/.*SELECT _postgis_drop_function_by_signature\('([^']*)'.*/$1/;

		handle_function_signature($line);
	}
}