[SCM] PostGIS branch stable-3.6 updated. 3.6.2-8-g5ff3eaca5

git at osgeo.org git at osgeo.org
Tue Mar 17 16:07:41 PDT 2026


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, stable-3.6 has been updated
       via  5ff3eaca52ba8db6d45e46c3b40c91b0b9c49248 (commit)
      from  e5be73640efdd333ed6358c442233d269f2dbc5f (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 5ff3eaca52ba8db6d45e46c3b40c91b0b9c49248
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Tue Mar 17 16:07:28 2026 -0700

    Function qualification improvements to avoid name squatting during upgrades
    References #6055

diff --git a/extensions/postgis/Makefile.in b/extensions/postgis/Makefile.in
index 537a501a7..88ef35afd 100644
--- a/extensions/postgis/Makefile.in
+++ b/extensions/postgis/Makefile.in
@@ -129,8 +129,10 @@ sql/postgis_for_extension.sql: ../../postgis/postgis.sql.in ../../postgis_revisi
 	rm -f $@.tmp
 
 sql/postgis_upgrade.sql: sql/postgis_upgrade_for_extension.sql | sql
-	$(PERL) -pe "s/BEGIN\;//g ; s/COMMIT\;//g; s/^(DROP .*)\;/SELECT postgis_extension_drop_if_exists('$(EXTENSION)', '\1');\n\1\;/" $< > $@
-
+	cat $< | \
+	$(PERL) -lpe "s/BEGIN\;//g" | \
+	$(PERL) -lpe "s/COMMIT\;//g" | \
+	$(PERL) -lpe "s/^(DROP .*)\;/SELECT \@extschema\@.postgis_extension_drop_if_exists('$(EXTENSION)', '\1');\n\1\;/" > $@
 
 sql/$(EXTENSION)--ANY--$(EXTVERSION).sql: $(EXTENSION_UPGRADE_SCRIPTS) | sql
 	printf '\\echo Use "CREATE EXTENSION $(EXTENSION)" to load this file. \\quit\n' > $@
diff --git a/extensions/postgis_extension_helper.sql.in b/extensions/postgis_extension_helper.sql.in
index 3341f9ef1..4855ea882 100644
--- a/extensions/postgis_extension_helper.sql.in
+++ b/extensions/postgis_extension_helper.sql.in
@@ -18,7 +18,9 @@ CREATE FUNCTION postgis_extension_drop_if_exists(param_extension text, param_sta
   RETURNS boolean AS
 $$
 DECLARE
-	var_sql_ext text := 'ALTER EXTENSION ' OPERATOR(pg_catalog.||) pg_catalog.quote_ident(param_extension) OPERATOR(pg_catalog.||) ' ' OPERATOR(pg_catalog.||) pg_catalog.replace(param_statement, 'IF EXISTS', '');
+	var_sql_ext text := pg_catalog.format('ALTER EXTENSION %s %s',
+		pg_catalog.quote_ident(param_extension),
+		pg_catalog.replace(param_statement, 'IF EXISTS', ''));
 	var_result boolean := false;
 BEGIN
 	BEGIN
@@ -26,13 +28,13 @@ BEGIN
 		var_result := true;
 	EXCEPTION
 		WHEN OTHERS THEN
-			--this is to allow ignoring if the object does not exist in extension
+			-- This is to allow ignoring if the object does not exist in extension
 			var_result := false;
 	END;
 	RETURN var_result;
 END;
 $$
-LANGUAGE plpgsql VOLATILE;
+LANGUAGE 'plpgsql' VOLATILE;
 
 CREATE FUNCTION postgis_extension_AddToSearchPath(a_schema_name text)
 #include "libpgcommon/sql/AddToSearchPath.sql.inc"
diff --git a/extensions/postgis_extension_helper_uninstall.sql b/extensions/postgis_extension_helper_uninstall.sql
index 756dc80f8..c582d3511 100644
--- a/extensions/postgis_extension_helper_uninstall.sql
+++ b/extensions/postgis_extension_helper_uninstall.sql
@@ -13,6 +13,6 @@
 --
 -- This drops extension helper functions
 -- and should be called at the end of the extension upgrade file
-DROP FUNCTION postgis_extension_drop_if_exists(text, text);
+DROP FUNCTION IF EXISTS postgis_extension_drop_if_exists(text, text);
 DROP FUNCTION IF EXISTS postgis_extension_AddToSearchPath(varchar);
 DROP FUNCTION IF EXISTS postgis_extension_AddToSearchPath(text);
diff --git a/extensions/postgis_raster/Makefile.in b/extensions/postgis_raster/Makefile.in
index b174746f9..857ce15de 100644
--- a/extensions/postgis_raster/Makefile.in
+++ b/extensions/postgis_raster/Makefile.in
@@ -97,7 +97,10 @@ sql/rtpostgis_for_extension.sql: ../../raster/rt_pg/rtpostgis.sql.in ../../postg
 	rm -f $@.tmp
 
 sql/rtpostgis_upgrade.sql: sql/rtpostgis_upgrade_for_extension.sql | sql
-	$(PERL) -pe "s/BEGIN\;//g ; s/COMMIT\;//g; s/^(DROP .*)\;/SELECT postgis_extension_drop_if_exists('$(EXTENSION)', '\1');\n\1\;/" $< > $@
+	cat $< | \
+	$(PERL) -lpe "s/BEGIN\;//g" | \
+	$(PERL) -lpe "s/COMMIT\;//g" | \
+	$(PERL) -lpe "s/^(DROP .*)\;/SELECT \@extschema\@.postgis_extension_drop_if_exists('$(EXTENSION)', '\1');\n\1\;/" > $@
 
 #this keeps the @extschema at . in place since extension machinery will replace during install
 sql/rtpostgis_upgrade_for_extension.sql: ../../postgis/common_before_upgrade.sql ../../raster/rt_pg/rtpostgis_upgrade_cleanup.sql sql/rtpostgis_upgrade_for_extension.sql.in ../../raster/rt_pg/rtpostgis_drop.sql ../../postgis/common_after_upgrade.sql | sql
diff --git a/postgis/Makefile.in b/postgis/Makefile.in
index 03955ba39..887dd5f19 100644
--- a/postgis/Makefile.in
+++ b/postgis/Makefile.in
@@ -241,14 +241,15 @@ endif
 #
 %.sql: %.sql.in
 	$(SQLPP) -I at top_srcdir@/libpgcommon -I at builddir@ $< > $@.tmp
-	grep -v '^#' $@.tmp | $(PERL) -lpe "s'MODULE_PATHNAME'\$(MODULEPATH)'g;s'@extschema@\.''g" > $@
+	grep -v '^#' $@.tmp | \
+		$(PERL) -lpe "s'MODULE_PATHNAME'\$(MODULEPATH)'g" | \
+		$(PERL) -lpe "s'@extschema@\.''g" > $@
 	rm -f $@.tmp
 
 #this is redundant but trying to fold in with extension just hangs
 postgis_upgrade.sql.in: postgis.sql ../utils/create_upgrade.pl
 	$(PERL) @top_srcdir@/utils/create_upgrade.pl $< > $@
 
-
 postgis_upgrade.sql: common_before_upgrade.sql postgis_before_upgrade.sql postgis_upgrade.sql.in postgis_after_upgrade.sql common_after_upgrade.sql
 	echo "BEGIN;" > $@
 	cat $^ >> $@
diff --git a/postgis/common_before_upgrade.sql b/postgis/common_before_upgrade.sql
index 222b5f1f5..be721bfe9 100644
--- a/postgis/common_before_upgrade.sql
+++ b/postgis/common_before_upgrade.sql
@@ -42,8 +42,8 @@ DECLARE
 	postgis_namespace OID;
 	matching_function pg_catalog.pg_proc;
 	detail TEXT;
-	deprecated_suffix TEXT := '_deprecated_by_postgis_' || deprecated_in_version;
-  deprecated_suffix_len INT := length(deprecated_suffix);
+	deprecated_suffix TEXT := pg_catalog.concat('_deprecated_by_postgis_', deprecated_in_version);
+  deprecated_suffix_len INT := pg_catalog.length(deprecated_suffix);
 BEGIN
 
 	-- Fetch install namespace for PostGIS
@@ -57,15 +57,16 @@ BEGIN
 	SELECT *
 	FROM pg_catalog.pg_proc p
 	WHERE pronamespace = postgis_namespace
-	AND pg_catalog.LOWER(p.proname) = pg_catalog.LOWER(function_name)
+	AND p.proname ILIKE function_name
 	AND pg_catalog.pg_function_is_visible(p.oid)
-	AND pg_catalog.LOWER(pg_catalog.pg_get_function_identity_arguments(p.oid)) = pg_catalog.LOWER(function_arguments)
+	AND pg_catalog.pg_get_function_identity_arguments(p.oid) ILIKE function_arguments
 	INTO matching_function;
 
 	IF matching_function.oid IS NOT NULL THEN
-		sql := format('ALTER FUNCTION %s RENAME TO %I',
+		sql := pg_catalog.format('ALTER FUNCTION %s RENAME TO %I',
 			matching_function.oid::regprocedure,
-			SUBSTRING(matching_function.proname,1,63-deprecated_suffix_len) || deprecated_suffix --limit to 63 characters
+			--limit to 63 characters
+			pg_catalog.concat(pg_catalog.left(matching_function.proname,63-deprecated_suffix_len), deprecated_suffix)
 		);
 		RAISE DEBUG 'SQL query: %', sql;
 		BEGIN
@@ -99,8 +100,8 @@ BEGIN
 		SELECT castsource::pg_catalog.regtype::text, casttarget::pg_catalog.regtype::text
 		INTO STRICT cast_source, cast_target
 		FROM pg_catalog.pg_cast
-    WHERE castsource::pg_catalog.regtype::text = lower(sourcetype)
-		AND casttarget::pg_catalog.regtype::text = lower(targettype);
+    WHERE castsource::pg_catalog.regtype::text ILIKE sourcetype
+		AND casttarget::pg_catalog.regtype::text ILIKE targettype;
 	EXCEPTION
 	WHEN NO_DATA_FOUND THEN
 		RAISE DEBUG 'Deprecated cast (topology.% as %) does not exist', sourcetype, targettype;
@@ -113,7 +114,7 @@ BEGIN
 		RETURN;
 	END;
 
-	new_name := cast_source || '_' || cast_target;
+	new_name := pg_catalog.concat(cast_source, '_', cast_target);
 	sql := pg_catalog.format(
 		'DROP CAST IF EXISTS (topology.%s AS %s)',
 		cast_source,
@@ -135,7 +136,7 @@ DECLARE
 	newname TEXT;
 	proc RECORD;
 	deprecated_suffix TEXT := '_deprecated_by_postgis_' || deprecated_in_version;
-	deprecated_suffix_len INT := length(deprecated_suffix);
+	deprecated_suffix_len INT := pg_catalog.length(deprecated_suffix);
 BEGIN
 
 	-- Check if the deprecated function exists
@@ -161,7 +162,8 @@ BEGIN
 	sql := pg_catalog.format(
 		'ALTER FUNCTION %s RENAME TO %I',
 		proc.oid::regprocedure,
-		SUBSTRING(proc.proname,1,63-deprecated_suffix_len) || deprecated_suffix -- limit to 63 characters
+		-- limit to 63 characters
+		pg_catalog.concat(pg_catalog.left(proc.proname,63-deprecated_suffix_len), deprecated_suffix)
 	);
 	EXECUTE sql;
 
@@ -177,14 +179,14 @@ CREATE OR REPLACE FUNCTION _postgis_topology_upgrade_domain_type(
 DECLARE
 	detail TEXT;
 	-- We need the base types of the old and new types - if multidimensional (int[][]), we need just one dimension at most
-	old_base_type TEXT := regexp_replace(old_domain_type, E'(\\[\\])+$', '[]');
-	new_base_type TEXT := regexp_replace(new_domain_type, E'(\\[\\])+$', '[]');
-	array_dims INT := (SELECT count(*) FROM regexp_matches (old_domain_type, E'\\[\\]', 'g'));
+	old_base_type TEXT := pg_catalog.regexp_replace(old_domain_type, E'(\\[\\])+$', '[]');
+	new_base_type TEXT := pg_catalog.regexp_replace(new_domain_type, E'(\\[\\])+$', '[]');
+	array_dims INT := (SELECT count(*) FROM pg_catalog.regexp_matches (old_domain_type, E'\\[\\]', 'g'));
 BEGIN
 	IF EXISTS (SELECT 1 FROM pg_catalog.pg_type AS t
 		WHERE  typnamespace::regnamespace::text = 'topology'
-		AND typname::text = lower(domain_name)
-		AND typbasetype::regtype::text = lower(old_base_type)
+		AND typname::text ILIKE domain_name
+		AND typbasetype::regtype::text ILIKE old_base_type
     AND typndims = array_dims)
   	THEN
 		BEGIN
@@ -192,8 +194,8 @@ BEGIN
 			UPDATE pg_catalog.pg_type
 			SET typbasetype = new_base_type::regtype::oid, typndims = array_dims
 			WHERE typnamespace::regnamespace::text = 'topology'
-			AND typname::text = lower(domain_name)
-			AND typbasetype::regtype::text = lower(old_base_type)
+			AND typname::text ILIKE domain_name
+			AND typbasetype::regtype::text ILIKE old_base_type
 			AND typndims = array_dims;
 
 			RAISE INFO 'Upgraded % from % to %', domain_name, old_domain_type, new_domain_type;
@@ -221,6 +223,7 @@ CREATE OR REPLACE FUNCTION _postgis_topology_upgrade_user_type_attribute(
 DECLARE
 	sql text;
 	detail TEXT;
+	tmp text;
 	num_updated integer;
 	proc RECORD;
 	temp_attr_name TEXT := attr_name || '_tmp';
@@ -232,13 +235,13 @@ BEGIN
 		-- Get the attribute id and number of attributes (so we can reset relnatts after adding/deleting temp attribute)
 		SELECT pg_type.typrelid attrelid, pg_class.relnatts
 		FROM pg_catalog.pg_type
-			join pg_class on pg_class.oid = pg_type.typrelid
-			join pg_attribute on pg_attribute.attrelid = pg_class.oid
-			join pg_type as pg_attr_type on pg_attr_type.oid = pg_attribute.atttypid
-		where pg_type.typname::regtype::text = lower(type_name)
+			join pg_catalog.pg_class on pg_class.oid = pg_type.typrelid
+			join pg_catalog.pg_attribute on pg_attribute.attrelid = pg_class.oid
+			join pg_catalog.pg_type as pg_attr_type on pg_attr_type.oid = pg_attribute.atttypid
+		where pg_type.typname::regtype::text ILIKE type_name
 		and pg_type.typnamespace::regnamespace::text = 'topology'
-		and attname::text = lower(attr_name)
-		and pg_attr_type.typname::regtype::text = lower(old_attr_type)
+		and attname::text ILIKE attr_name
+		and pg_attr_type.typname::regtype::text ILIKE old_attr_type
 		INTO STRICT proc;
 
 	EXCEPTION
@@ -256,57 +259,57 @@ BEGIN
 	BEGIN
 		-- Add a temporary attribute with the required type
 		-- This is the cleanest way to ensure the type is valid and all constraints are met
-		sql := format(
+		sql := pg_catalog.format(
 			'ALTER TYPE topology.%s ADD ATTRIBUTE %s %s',
 			type_name,
 			temp_attr_name,
 			new_attr_type
 		);
-		--RAISE INFO 'SQL: %', sql;
+		RAISE DEBUG 'SQL: %', sql;
 		EXECUTE sql;
 
 		-- Copy the attributes from the temp attribute to the existing attribute
 		sql := 'UPDATE pg_attribute AS tgt SET ';
 
 		BEGIN
-  		FOR colname IN
-    	SELECT column_name
-    	FROM information_schema.columns
-    	WHERE table_name = 'pg_attribute'
-      AND column_name <> ALL (excluded_columns)
-			AND column_name NOT LIKE 'oid%' -- Exclude system columns
-  		LOOP
-    		sql := sql || format('%I = src.%I, ', colname, colname);
-  		END LOOP;
+			-- add in tgt = src assignments for the update
+			SELECT pg_catalog.string_agg(pg_catalog.format('%I = src.%I', column_name, column_name), ', ')
+			FROM information_schema.columns
+			INTO tmp
+			WHERE table_name = 'pg_attribute'
+			AND column_name <> ALL (excluded_columns)
+			AND column_name NOT LIKE 'oid%';
+			sql := sql || tmp;
 
-  		-- remove trailing comma and add FROM/WHERE clause
-  		sql := left(sql, -2) || ' FROM pg_attribute AS src WHERE ' || format('tgt.attrelid = %s AND tgt.attname = %L AND src.attrelid = %s AND src.attname = %L',
+			-- add FROM/WHERE clause
+			tmp := pg_catalog.format('tgt.attrelid = %s AND tgt.attname = %L AND src.attrelid = %s AND src.attname = %L',
 				proc.attrelid,
 				attr_name,
 				proc.attrelid,
 				temp_attr_name
 			);
+			sql := pg_catalog.concat(sql, ' FROM pg_attribute AS src WHERE ', tmp);
 
-  		--RAISE INFO 'SQL: %', sql;
-  		EXECUTE sql;
+			RAISE DEBUG 'SQL: %', sql;
+			EXECUTE sql;
 		END;
 
 		-- Delete temp attribute since we cannot alter the type
-		sql := format(
+		sql := pg_catalog.format(
 			'DELETE FROM pg_attribute WHERE attname = %L AND attrelid = %s',
 			temp_attr_name,
 			proc.attrelid
 		);
-		--RAISE INFO 'SQL: %', sql;
+		RAISE DEBUG 'SQL: %', sql;
 		EXECUTE sql;
 
 		-- Reset the number of attributes in pg_class else postgres will complain
-		sql := format(
+		sql := pg_catalog.format(
 				'UPDATE pg_class SET relnatts = %s WHERE oid = %s',
 				proc.relnatts,
 				proc.attrelid
 		);
-		--RAISE INFO 'SQL: %', sql;
+		RAISE DEBUG 'SQL: %', sql;
 		EXECUTE sql;
 
 		RAISE INFO 'Upgraded %.% from % to %', type_name, attr_name, old_attr_type, new_attr_type;
@@ -319,7 +322,7 @@ BEGIN
 		RETURN;
 	END;
 END;
-$$ LANGUAGE plpgsql;
+$$ LANGUAGE 'plpgsql';
 
 -- Add useslargeids to topology
 CREATE OR REPLACE FUNCTION _postgis_add_column_to_table(
@@ -351,7 +354,7 @@ BEGIN
 			null_clause := 'NOT NULL';
 		END IF;
 
-		IF LENGTH(default_value) > 0 THEN
+		IF pg_catalog.LENGTH(default_value) > 0 THEN
 			default_clause := 'DEFAULT ' || default_value;
 		END IF;
 
@@ -367,7 +370,7 @@ BEGIN
 			default_clause
 		);
 
-		--RAISE INFO 'SQL: %', sql;
+		-- RAISE INFO 'SQL: %', sql;
 		EXECUTE sql;
 
 
diff --git a/utils/create_uninstall.pl b/utils/create_uninstall.pl
index 86f40041e..fab98cfd8 100755
--- a/utils/create_uninstall.pl
+++ b/utils/create_uninstall.pl
@@ -287,10 +287,10 @@ DECLARE
 BEGIN
 	FOR rec IN
 		SELECT n.nspname, c.relname, a.attname, t.typname
-		FROM pg_attribute a
-		JOIN pg_class c ON a.attrelid = c.oid
-		JOIN pg_namespace n ON c.relnamespace = n.oid
-		JOIN pg_type t ON a.atttypid = t.oid
+		FROM pg_catalog.pg_attribute a
+		JOIN pg_catalog.pg_class c ON a.attrelid = c.oid
+		JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
+		JOIN pg_catalog.pg_type t ON a.atttypid = t.oid
 		WHERE t.typname = '$type'
 		  AND NOT (
 				-- we exclude complexes defined as types
@@ -398,16 +398,16 @@ DECLARE
 	var_result text;
 	var_search_path text;
 BEGIN
-	SELECT reset_val INTO var_search_path FROM pg_settings WHERE name = 'search_path';
-	IF var_search_path NOT LIKE '%' || quote_ident(a_schema_name) || '%' THEN
+	SELECT reset_val INTO var_search_path FROM pg_catalog.pg_settings WHERE name = 'search_path';
+	IF NOT var_search_path ~ pg_catalog.quote_ident(a_schema_name) THEN
 		var_result := a_schema_name || ' not in database search_path';
 	ELSE
-    var_search_path := btrim( regexp_replace(
-        replace(var_search_path, a_schema_name, ''), ', *,', ','),
+    var_search_path := pg_catalog.btrim( pg_catalog.regexp_replace(
+        pg_catalog.replace(var_search_path, a_schema_name, ''), ', *,', ','),
         ', ');
     RAISE NOTICE 'New search_path: %', var_search_path;
-		EXECUTE 'ALTER DATABASE ' || quote_ident(current_database()) || ' SET search_path = ' || var_search_path;
-		var_result := a_schema_name || ' has been stripped off database search_path ';
+		EXECUTE pg_catalog.Format('ALTER DATABASE %s SET search_path = %s', pg_catalog.quote_ident(current_database()), var_search_path);
+		var_result := pg_catalog.Concat(a_schema_name, ' has been stripped off database search_path ');
 	END IF;
 
   RETURN var_result;
diff --git a/utils/create_upgrade.pl b/utils/create_upgrade.pl
index f4bb9adc1..38826cfe6 100644
--- a/utils/create_upgrade.pl
+++ b/utils/create_upgrade.pl
@@ -125,10 +125,18 @@ while(<INPUT>)
 
         #last;
     }
+    elsif (/CREATE SCHEMA topology/)
+    {
+        $module = 'postgis_topology';
+    }
     elsif (/TYPE raster/)
     {
         $module = 'postgis_raster';
     }
+    elsif (/FUNCTION postgis_sfcgal_noop/)
+    {
+        $module = 'postgis_sfcgal';
+    }
     elsif (m@('\$libdir/[^']*')@)
     {
         $soname = $1;

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

Summary of changes:
 extensions/postgis/Makefile.in                    |  6 +-
 extensions/postgis_extension_helper.sql.in        |  8 +-
 extensions/postgis_extension_helper_uninstall.sql |  2 +-
 extensions/postgis_raster/Makefile.in             |  5 +-
 postgis/Makefile.in                               |  5 +-
 postgis/common_before_upgrade.sql                 | 97 ++++++++++++-----------
 utils/create_uninstall.pl                         | 20 ++---
 utils/create_upgrade.pl                           |  8 ++
 8 files changed, 85 insertions(+), 66 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list