[SCM] PostGIS branch master updated. 3.5.0-441-g0aa8924b9

git at osgeo.org git at osgeo.org
Wed Jul 9 19:13:03 PDT 2025


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  0aa8924b94a4d2de477e0fa0f9b0f47ee98218ff (commit)
      from  d049349da81b6f18ceb318260bc60014cb76abbc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0aa8924b94a4d2de477e0fa0f9b0f47ee98218ff
Author: Ayo Adesugba <ayoadesugba at gmail.com>
Date:   Tue Jul 1 00:16:45 2025 -0400

    Closes #3373 support for topology upgrading domains
    Closes https://git.osgeo.org/gitea/postgis/postgis/pulls/255
    References https://git.osgeo.org/gitea/postgis/postgis/pulls/255
    Closes https://github.com/postgis/postgis/pull/821
    References https://github.com/postgis/postgis/pull/821
    
    Minor change to combine the create domain with all constraints for same available version.
    
    Fix the create_upgrade script to handle domains
    
    Fixed the create domain handler
    
    Add to NEWS and credits

diff --git a/NEWS b/NEWS
index 7952cfacb..583a31c6b 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ Daniel Nylander (Swedish Team)
 
   - #5799, make ST_TileEnvelope clips envelopes to tile plane extent (Paul Ramsey)
   - #5829, remove constraint checking from geometry_columns view (Paul Ramsey)
+  - #3373, GT-255 [topology] Support for upgrading domains (Ayo Adesugba, U.S. Census Bureau)
 
 * Deprecated signatures *
 
diff --git a/doc/introduction.xml b/doc/introduction.xml
index 91034b489..98c4af7b5 100644
--- a/doc/introduction.xml
+++ b/doc/introduction.xml
@@ -231,6 +231,7 @@
 					<member>Antoine Bajolet</member>
 					<member>Arthur Lesuisse</member>
 					<member>Artur Zakirov</member>
+					<member>Ayo Adesugba</member>
 					<member>Barbara Phillipot</member>
 					<member>Ben Jubb</member>
 					<member>Bernhard Reiter</member>
@@ -401,6 +402,7 @@
 				<listitem><simpara><link xlink:href="http://www.uster.ch">Stadt Uster</link></simpara></listitem>
 				<listitem><simpara><link xlink:href="https://www.ucdavis.edu">UC Davis Center for Vectorborne Diseases</link></simpara></listitem>
 				<listitem><simpara><link xlink:href="https://www.ulaval.ca">Université Laval</link></simpara></listitem>
+				<listitem><simpara><link xlink:href="https://www.census.gov">U.S. Census Bureau</link></simpara></listitem>
 				<listitem><simpara><link xlink:href="https://hiu.state.gov">U.S. Department of State (HIU)</link></simpara></listitem>
 				<listitem><simpara><link xlink:href="https://www.zonarsystems.com">Zonar Systems</link></simpara></listitem>
 			</itemizedlist>
diff --git a/topology/topology.sql.in b/topology/topology.sql.in
index 91d603ea6..64997937a 100644
--- a/topology/topology.sql.in
+++ b/topology/topology.sql.in
@@ -350,45 +350,40 @@ CREATE TYPE topology.TopoGeometry AS (
 -- element_type will be the child layer identifier and
 -- element_id will be composing TopoGeometry identifier
 --
+-- Availability: 1.1.0
 CREATE DOMAIN topology.TopoElement AS integer[]
+  -- Availability: 1.1.0
   CONSTRAINT DIMENSIONS CHECK (
     array_upper(VALUE, 2) IS NULL
     AND array_upper(VALUE, 1) = 2
-  );
-ALTER DOMAIN topology.TopoElement ADD
-        CONSTRAINT lower_dimension CHECK (
-    array_lower(VALUE, 1) = 1
-  );
-ALTER DOMAIN topology.TopoElement DROP CONSTRAINT
-  IF EXISTS
-  type_range;
-ALTER DOMAIN topology.TopoElement ADD
-        CONSTRAINT type_range CHECK (
+  )
+  -- Availability: 1.1.0
+  CONSTRAINT type_range CHECK (
     VALUE[2] > 0
+  )
+  -- Availability: 2.0.0
+  CONSTRAINT lower_dimension CHECK (
+    array_lower(VALUE, 1) = 1
   );
 
 --
 -- TopoElementArray domain
 --
--- Changed: 3.1.0 - get rid of IS NOT NULL check
+-- Availability: 1.1.0
 CREATE DOMAIN topology.TopoElementArray AS integer[][]
+  -- Availability: 1.1.0
+	-- Changed: 3.1.0 - get rid of IS NOT NULL check
   CONSTRAINT DIMENSIONS CHECK (
     array_upper(VALUE, 2) = 2
     AND array_upper(VALUE, 3) IS NULL
-  );
-
--- Changed: 3.1.0
-ALTER DOMAIN topology.TopoElementArray DROP CONSTRAINT
-  IF EXISTS
-  DIMENSIONS;
-
--- Changed: 3.1.0 - get rid of IS NOT NULL check
-ALTER DOMAIN topology.TopoElementArray ADD
-        CONSTRAINT type_range CHECK (
+  )
+  -- Availability: 3.1.0
+  CONSTRAINT type_range CHECK (
     array_upper(VALUE, 2) = 2
     AND array_upper(VALUE, 3) IS NULL
   );
 
+
 --{ RelationTrigger()
 --
 -- Relation integrity trigger
diff --git a/utils/create_upgrade.pl b/utils/create_upgrade.pl
old mode 100755
new mode 100644
index 79af6fa8b..b4f51985c
--- a/utils/create_upgrade.pl
+++ b/utils/create_upgrade.pl
@@ -79,6 +79,14 @@ sub parse_missing
     return join(',', at missing);
 }
 
+sub remove_line_break
+{
+    my $line = shift;
+    $line =~ s/\s+/ /g;      # Replace all whitespace (including newlines, tabs) with single spaces
+    $line =~ s/^\s+|\s+$//g; # Trim leading and trailing whitespace
+    return $line;
+}
+
 #
 # Commandline argument handling
 #
@@ -187,6 +195,220 @@ while(<INPUT>)
     print if (/^drop function /i);
     print if (/^drop aggregate /i);
 
+    if (/^create domain\s+([^.]+)\.([^\s]+)\s+as\s+([^;]+)/i) {
+        my $schema = lc($1);
+        my $name   = lc($2);
+        my $type   = lc($3);
+        $type = remove_line_break($type); # Normalize whitespace using helper function
+
+        my $def .= $_;
+        my $subcomment = '';
+        my @constraints; # [type, definition, last_updated, comment]
+        my $type_changed = 0;
+        my $all_constraints_created_together = 1;
+
+        print "\n\n-- Domain: $schema.$name($type)\n";
+
+        my @replaced_array = parse_replaces($comment);
+
+        my $domain_last_updated = parse_last_updated($comment);
+        if ( !$domain_last_updated )
+        {
+            die "ERROR: no last updated info for domain  '${schema}.${name}($type)'\n";
+        }
+        my $missing = parse_missing($comment);
+
+        unless (/;\s*$/) {
+            while(my $line = <INPUT>) {
+                if ($line =~ /^\s*\-\-/) {
+                    $subcomment .= remove_line_break($line);
+                    next;
+                }
+
+                # Find NOT NULL or NULL constraint in domain definition ignore ;
+                if ($line =~ /^\s*(NOT\s+NULL|NULL)\s*;?\s*$/i) {
+                    my $ctype = uc($1);
+
+                    my $last_updated = parse_last_updated($subcomment);
+                    my $missing = parse_missing($subcomment);
+
+                    if ( $last_updated ) {
+                        push @constraints, [$ctype, '', $ctype, $last_updated, $missing, $subcomment];
+                    } else {
+                        die "ERROR: no last updated info for constraint '${ctype}' in ${schema}.${name}($type)\n";
+                    }
+
+                    $subcomment = '';
+
+                    if ($line =~ /;\s*$/) {
+                        $def .= "$ctype;\n";
+                        last;
+                    } else {
+                        $def .= "$ctype\n";
+                    }
+
+                    next;
+                }
+
+                if ($line =~ /CONSTRAINT\s+(\w+)\s+CHECK/i) {
+                    my $constraint_name = $1;
+                    my $constraint = $line;
+                    my $open_parens = ($constraint =~ tr/(//);
+                    my $close_parens = ($constraint =~ tr/)//);
+                    my $found_semicolon = 0;
+
+                    while ($open_parens == 0 || $open_parens > $close_parens) {
+                        my $nextline = <INPUT>;
+                        last unless defined $nextline;
+
+                        if ($nextline =~ /;\s*$/) {
+                            $found_semicolon = 1;
+                            $nextline =~ s/;\s*$//;
+                        }
+
+                        $constraint .= $nextline;
+                        $open_parens += ($nextline =~ tr/(//);
+                        $close_parens += ($nextline =~ tr/)//);
+                    }
+
+                    # Make a single line of the constraint
+                    $constraint = remove_line_break($constraint);
+
+                    my $last_updated = parse_last_updated($subcomment);
+                    my $missing = parse_missing($subcomment);
+
+                    if ( $last_updated ) {
+                        push @constraints, ['CHECK', $constraint_name, $constraint, $last_updated, $missing, $subcomment];
+                    } else {
+                        die "ERROR: no last updated info for constraint '${constraint_name}' in ${schema}.${name}($type)\n";
+                    }
+
+                    $subcomment = ''; # Reset subcomment after using it
+
+                    if ($found_semicolon) {
+                        $def .= "$constraint;\n";
+                        last;
+                    } else {
+                        $def .= "$constraint\n";
+                    }
+
+                    next;
+                }
+
+                last if $line =~ /;\s*$/;  # End of domain definition
+            }
+        }
+
+        foreach my $c (@constraints) {
+            my ($ctype, $cname, $cdef, $last_updated, $missing, $comment) = @$c;
+
+            if ($domain_last_updated != $last_updated) {
+                $all_constraints_created_together = 0;
+            }
+        }
+
+        if (@replaced_array) {
+            foreach my $replaced(@replaced_array)
+            {
+                my ($rname, $rargs, $ver) = @$replaced;
+                $rname = lc($rname); # lowercase the name
+                my $old_type = lc($rargs);
+                my $new_type = lc($type);
+
+                if ($old_type ne $new_type)
+                {
+                    $type_changed = 1;
+                    print <<"EOF";
+-- ${schema}.${name}($old_type) -- LastUpdated: ${domain_last_updated}
+-- Updated Domain ${schema}.${name}($new_type)
+-- We cannot drop the old domain, so we modify it
+DO LANGUAGE 'plpgsql'
+\$postgis_domain_upgrade\$
+BEGIN
+IF $ver > version_from_num
+EOF
+                    print "OR version_from_num IN ( ${missing} )" if ($missing);
+                    print <<"EOF";
+    FROM _postgis_upgrade_info()
+THEN
+    IF EXISTS (SELECT 1 FROM pg_catalog.pg_type AS t
+        WHERE  typnamespace::regnamespace::text = 'topology'
+        AND typname = '$name' AND typbasetype::regtype::text = '$old_type')
+    THEN
+        UPDATE pg_catalog.pg_type SET typbasetype = '$new_type'::regtype::oid
+        WHERE typnamespace::regnamespace::text = 'topology'
+        AND typname::text = '$name' AND typbasetype::regtype::text = '$old_type';
+EOF
+                    foreach my $c (@constraints) {
+                        my ($ctype, $cname, $cdef, $last_updated, $missing, $comment) = @$c;
+
+                        print <<"EOF";
+        EXECUTE \$postgis_domain_upgrade_parsed_def\$ ALTER DOMAIN ${schema}.${name} DROP CONSTRAINT IF EXISTS $cname \$postgis_domain_upgrade_parsed_def\$;
+        EXECUTE \$postgis_domain_upgrade_parsed_def\$ ALTER DOMAIN ${schema}.${name} ADD $cdef \$postgis_domain_upgrade_parsed_def\$;
+EOF
+                    }
+                    print <<"EOF";
+        RAISE DEBUG 'Upgraded % from % to %', '$name', '$old_type', '$new_type';
+    END IF;
+END IF;
+END
+\$postgis_domain_upgrade\$;\n
+EOF
+                }
+            }
+        } elsif ($all_constraints_created_together) {
+            print <<"EOF";
+DO LANGUAGE 'plpgsql'
+\$postgis_domain_upgrade\$
+BEGIN
+IF $domain_last_updated > version_from_num
+EOF
+            print "OR version_from_num IN ( ${missing} )\n" if ($missing);
+            print <<"EOF";
+FROM _postgis_upgrade_info()
+THEN
+    EXECUTE \$postgis_domain_upgrade_parsed_def\$ $def \$postgis_domain_upgrade_parsed_def\$;
+END IF;
+END
+\$postgis_domain_upgrade\$;
+EOF
+        } else {
+            foreach my $c (@constraints) {
+                my ($ctype, $cname, $cdef, $last_updated, $missing, $comment) = @$c;
+
+                print <<"EOF";
+DO LANGUAGE 'plpgsql'
+\$postgis_domain_upgrade\$
+BEGIN
+IF $last_updated > version_from_num
+EOF
+            print "OR version_from_num IN ( ${missing} )\n" if ($missing);
+            print <<"EOF";
+FROM _postgis_upgrade_info()
+THEN
+    EXECUTE \$postgis_domain_upgrade_parsed_def\$ ALTER DOMAIN ${schema}.${name} DROP CONSTRAINT IF EXISTS $cname \$postgis_domain_upgrade_parsed_def\$;
+    EXECUTE \$postgis_domain_upgrade_parsed_def\$ ALTER DOMAIN ${schema}.${name} ADD $cdef \$postgis_domain_upgrade_parsed_def\$;
+END IF;
+END
+\$postgis_domain_upgrade\$;
+EOF
+                print "\n";
+            }
+        }
+    }
+
+    if (/^alter\s+domain\s+([^.]+)\.([^\s]+)\s/ims)
+    {
+        # This is a domain alteration, which we do not support in upgrade scripts
+        # since we cannot drop and recreate domains.
+        # We will just die with an error message.
+        my $schema = $1;
+        my $name   = remove_line_break(lc($2));
+        #print "Altering domain $schema.$name is not supported in upgrade scripts.\n";
+        # Die if we find an ALTER DOMAIN command
+        die "ERROR: ALTER DOMAIN command found for domain '${name}'\n";
+    }
+
     if (/^create or replace function/i)
     {
         my $def .= $_;
@@ -784,3 +1006,4 @@ END
 $$
 LANGUAGE 'plpgsql';
 
+

-----------------------------------------------------------------------

Summary of changes:
 NEWS                     |   1 +
 doc/introduction.xml     |   2 +
 topology/topology.sql.in |  37 ++++----
 utils/create_upgrade.pl  | 223 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 242 insertions(+), 21 deletions(-)
 mode change 100755 => 100644 utils/create_upgrade.pl


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list