[Git][debian-gis-team/postgis][upstream] New upstream version 3.6.4+dfsg

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Tue Jun 9 05:15:38 BST 2026



Bas Couwenberg pushed to branch upstream at Debian GIS Project / postgis


Commits:
982f263c by Bas Couwenberg at 2026-06-09T05:54:02+02:00
New upstream version 3.6.4+dfsg
- - - - -


23 changed files:

- ChangeLog
- NEWS
- README.postgis
- Version.config
- doc/reference_accessor.xml
- doc/release_notes.xml
- extensions/address_standardizer/Makefile
- extensions/upgradeable_versions.mk
- extras/tiger_geocoder/geocode/other_helper_functions.sql
- extras/tiger_geocoder/pagc_normalize/pagc_tables.sql
- liblwgeom/liblwgeom.h.in
- liblwgeom/lwgeodetic.c
- liblwgeom/lwgeom_geos_split.c
- libpgcommon/lwgeom_transform.c
- postgis/flatgeobuf.c
- postgis/geography_measurement.c
- postgis/lwgeom_geos_prepared.h
- postgis/lwgeom_in_flatgeobuf.c
- postgis/lwgeom_spheroid.c
- postgis_revision.h
- regress/core/geography.sql
- regress/core/geography_expected
- sfcgal/lwgeom_sfcgal.c


Changes:

=====================================
ChangeLog
=====================================
@@ -1,3 +1,87 @@
+2026-06-08  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS, README.postgis, Version.config, doc/release_notes.xml: Prep
+	for 3.6.4 release
+
+2026-06-08  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* libpgcommon/lwgeom_transform.c, postgis/lwgeom_geos_prepared.h: 
+	Remove unused PostgreSQL headers
+
+2026-06-04  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS: News entry for #3916
+
+2026-06-04  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* liblwgeom/lwgeom_geos_split.c: Avoid Inf looping and memory use in
+	ST_Split When fed with very large coordinates, ST_Split could be fooled into
+	an Inf loop, this fixes that case, closes #5916
+
+2026-06-02  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* extras/tiger_geocoder/geocode/other_helper_functions.sql,
+	extras/tiger_geocoder/pagc_normalize/pagc_tables.sql: Prefix
+	operators to avoid extension operator injection
+
+2026-05-29  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS: News item for #5988
+
+2026-05-29  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* libpgcommon/lwgeom_transform.c: pg_upgrade issue for non-standard
+	geography SRID When doing pg_upgrade on a table with Geography(type, srid) column,
+	where the SRID is specified, but not 4326, the SRID lookup code will
+	fail during schema transfer as the spatial_ref_sys table may be
+	missing and unable to lookup the SRID number. This "fix" leans on
+	the fact that most SRID numbers in PostGIS are already EPSG numbers
+	so the lookup can be skipped most times.
+
+2026-05-27  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS: News entry for flatgeobuf schema fix
+
+2026-05-27  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* postgis/flatgeobuf.c, postgis/lwgeom_in_flatgeobuf.c: Check that
+	user-provided flatbuffer schema matches The flatbuffer import maps an incoming file to a provided table
+	schema, and the consistency of those two schemes needs to be checked
+	before data are copied across.
+
+2026-05-25  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS: News entry for GH-862
+
+2026-05-25  Jean Felder <jean.felder at oslandia.com>
+
+	* sfcgal/lwgeom_sfcgal.c: sfcgal: Adapt to deprecated
+	sfcgal_geometry_tesselate `sfcgal_geometry_tessellate` is now used instead.
+
+2026-05-11  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS: News item for #6076
+
+2026-05-11  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* liblwgeom/liblwgeom.h.in, liblwgeom/lwgeodetic.c,
+	postgis/geography_measurement.c, postgis/lwgeom_spheroid.c,
+	regress/core/geography.sql, regress/core/geography_expected: Fix
+	ST_Length and ST_Perimeter for geography collections, closes #6076 ST_Length(geography) on collections now only sums linear components,
+	and ST_Perimeter(geography) now only sums areal components. Added
+	lwgeom_perimeter_spheroid to support the separation of logic.
+	Preserve legacy behaviour in ST_LengthSpheroid.
+
+2026-05-06  Jean Felder <jean.felder at oslandia.com>
+
+	* doc/reference_accessor.xml: doc: Fix typo in ST_GeometryN
+	documentation
+
+2026-04-14  Paul Ramsey <pramsey at cleverelephant.ca>
+
+	* NEWS, Version.config, extensions/upgradeable_versions.mk: Bump to
+	development 3.6.4
+
 2026-04-14  Paul Ramsey <pramsey at cleverelephant.ca>
 
 	* NEWS, README.postgis, Version.config, doc/release_notes.xml: 
@@ -43,92 +127,5 @@
 
 2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
 
-	* liblwgeom/lwstroke.c: Remove potential null dereference in
-	lwcircstring_linearize()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/measures3d.c: Remove potential null dereference in
-	pt_in_ring_3d()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/ptarray.c: Remove potential null dereference from
-	ptarray_contains_point_partial()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/liblwgeom.h.in, liblwgeom/liblwgeom_internal.h,
-	liblwgeom/lwalgorithm.c: Remove unused function pt_in_ring_2d()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/lwcompound.c: Remove reported crash in
-	lwcompound_add_lwgeom()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/lwcompound.c: Remove reported crash in
-	lwcompound_is_closed()
-
-2026-04-10  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* liblwgeom/effectivearea.c: Remove reported crash in
-	lwline_set_effective_area()
-
-2026-04-09  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* NEWS, liblwgeom/lwin_wkt_lex.c, liblwgeom/lwin_wkt_lex.l,
-	liblwgeom/lwutil.c: WKT parser produces incorrect error locations.
-	In extreme cases causes occasional crashes.  References #6061
-
-2026-04-08  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* NEWS, liblwgeom/measures.c: Clean up and add another special case
-	to lw_dist2d_pt_seg() When the seg is vertical or horizontal, we construct the nearest
-	points to avoid getting a difference between the more-exact distance
-	calculation that does not construct and the naturally constructive
-	process of building a bbox, which can result in a situation where
-	the "real distance" between two objects can be less than the "box
-	distance", which is simply not allowed.  References #6026
-
-2026-03-31  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* postgis/postgis.sql.in: Ensure that functions called in upgrade
-	script are fully qualified
-
-2026-03-23  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* NEWS, postgis/postgis.sql.in: Fully quality calls to helper
-	functions references #6060
-
-2026-03-20  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* NEWS, postgis/lwgeom_out_geojson.c: Use Pg composite_to_json()
-	function in 19+ References #6058
-
-2026-03-18  Ariel Mashraki <ariel at mashraki.co.il>
-
-	* raster/rt_pg/rtpg_mapalgebra.c,
-	raster/test/regress/rt_mapalgebra_expr.sql,
-	raster/test/regress/rt_mapalgebra_expr_expected: Use read-only SPI
-	execution for user-supplied expressions in ST_MapAlgebraExpr
-
-2026-03-17  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* extensions/postgis/Makefile.in,
-	extensions/postgis_extension_helper.sql.in,
-	extensions/postgis_extension_helper_uninstall.sql,
-	extensions/postgis_raster/Makefile.in, postgis/Makefile.in,
-	postgis/common_before_upgrade.sql, utils/create_uninstall.pl,
-	utils/create_upgrade.pl: Function qualification improvements to
-	avoid name squatting during upgrades References #6055
-
-2026-03-17  Paul Ramsey <pramsey at cleverelephant.ca>
-
-	* NEWS: NEWS item for GH-850
-
-2026-03-17  Ariel Mashraki <ariel at mashraki.co.il>
-
-	* Use quote_identifier to build tables in pgis_tablefromflatgeobuf
+	* Remove potential null dereference in lwcircstring_linearize()
 


=====================================
NEWS
=====================================
@@ -1,3 +1,16 @@
+PostGIS 3.6.4
+2026/06/08
+
+* Fixes *
+
+- #6076, ST_Length(geography) for GeometryCollection not consistent
+         with geometry implementation
+- GH-862, use SFCGAL undeprecated function sfcgal_geometry_tessellate() (Jean Felder)
+- Flatgeobuf schema mismatch vulnerability (NeuroWinter)
+- #5899, pg_upgrade issue for non-standard geography SRID (Paul Ramsey)
+- #5916, ST_Split hang with very large ordinates (Paul Ramsey)
+
+
 PostGIS 3.6.3
 2026/04/14
 


=====================================
README.postgis
=====================================
@@ -1,8 +1,8 @@
 PostGIS - Geographic Information Systems Extensions to PostgreSQL
 =================================================================
 
-:Version: 3.6.3
-:Date: 2026-04-14
+:Version: 3.6.4
+:Date: 2026-06-08
 :Website: https://postgis.net
 
 This distribution contains a module which implements GIS simple features, ties


=====================================
Version.config
=====================================
@@ -5,7 +5,7 @@
 
 POSTGIS_MAJOR_VERSION=3
 POSTGIS_MINOR_VERSION=6
-POSTGIS_MICRO_VERSION=3
+POSTGIS_MICRO_VERSION=4
 
 # Liblwgeom interface versioning, reset to 0:0:0 (cur:age:rev)
 # when changing POSTGIS_MINOR_VERSION


=====================================
doc/reference_accessor.xml
=====================================
@@ -1218,7 +1218,7 @@ LINESTRING(0 0 1,1 1 1,1 2 1,1 1 1,0 0 1)
 		<title>Description</title>
 
 		<para>Return the 1-based Nth element geometry of an input geometry which is a
-			GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTICURVE, MULTI)POLYGON, or POLYHEDRALSURFACE.
+			GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTICURVE, MULTIPOLYGON, or POLYHEDRALSURFACE.
 			Otherwise, returns NULL.</para>
 
 		<note>


=====================================
doc/release_notes.xml
=====================================
@@ -3,6 +3,19 @@
   <title>Appendix</title>
     <subtitle>Release Notes</subtitle>
 
+        <section>
+            <title>PostGIS 3.6.4</title>
+            <para>2026/06/08</para>
+
+            <simplesect>
+                <title>Fixes</title>
+                <para><link xlink:href="https://trac.osgeo.org/postgis/ticket/6076">6076</link>, ST_Length(geography) for GeometryCollection not consistent with geometry implementation</para>
+                <para><link xlink:href="https://github.com/postgis/postgis/pull/862">GH-862</link>, Use SFCGAL undeprecated function sfcgal_geometry_tessellate() (Jean Felder)</para>
+                <para>Flatgeobuf schema mismatch vulnerability (NeuroWinter)</para>
+                <para><link xlink:href="https://trac.osgeo.org/postgis/ticket/5899">5899</link>, pg_upgrade issue for non-standard geography SRID (Paul Ramsey)</para>
+                <para><link xlink:href="https://trac.osgeo.org/postgis/ticket/5916">5916</link>, ST_Split hang with very large ordinates (Paul Ramsey)</para>
+            </simplesect>
+        </section>
 
         <section>
             <title>PostGIS 3.6.3</title>


=====================================
extensions/address_standardizer/Makefile
=====================================
@@ -30,7 +30,7 @@ POSTGIS_PGSQL_VERSION=130
 # SQL preprocessor
 SQLPP = /bin/cpp -traditional-cpp -w -P -Upixel -Ubool
 GREP=/bin/grep
-EXTVERSION = 3.6.3
+EXTVERSION = 3.6.4
 MODULE_big = address_standardizer-3
 MODULEPATH    = $$libdir/address_standardizer-3
 ifeq (no,yes)
@@ -48,7 +48,7 @@ DATA_built = \
 	$(NULL)
 
 all:  sql/address_standardizer_pre.sql sql/address_standardizer.sql sql/address_standardizer--1.0--$(EXTVERSION).sql sql/$(EXTENSION)--$(EXTVERSION).sql sql/$(EXTENSION)--ANY--$(EXTVERSION).sql \
- sql/$(EXTENSION)_data_us.sql sql/address_standardizer--3.6.3.sql sql/$(EXTENSION)_data_us--3.6.3.sql  sql/$(EXTENSION)_data_us--$(EXTVERSION)--$(EXTVERSION)next.sql \
+ sql/$(EXTENSION)_data_us.sql sql/address_standardizer--3.6.4.sql sql/$(EXTENSION)_data_us--3.6.4.sql  sql/$(EXTENSION)_data_us--$(EXTVERSION)--$(EXTVERSION)next.sql \
 sql/$(EXTENSION)_data_us--$(EXTVERSION)next--$(EXTVERSION).sql sql/$(EXTENSION)_data_us--ANY--$(EXTVERSION).sql \
 sql/test-init-extensions.sql sql/test-parseaddress.sql sql/test-standardize_address_1.sql sql/test-standardize_address_2.sql sql/test-debug_standardize_address.sql
 


=====================================
extensions/upgradeable_versions.mk
=====================================
@@ -121,4 +121,5 @@ UPGRADEABLE_VERSIONS = \
 	3.5.5 \
 	3.6.0 \
 	3.6.1 \
-	3.6.2
+	3.6.2 \
+	3.6.3


=====================================
extras/tiger_geocoder/geocode/other_helper_functions.sql
=====================================
@@ -63,7 +63,7 @@ SELECT array_to_string(ARRAY(
 -- create unique index on faces for tfid seems to perform better --
 SELECT 'CREATE UNIQUE INDEX uidx_' || c.table_schema || '_' || c.table_name || '_' || c.column_name || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(' || c.column_name || ');' As index
 FROM (SELECT table_name, table_schema  FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE') As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE') As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('tfid') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -74,7 +74,7 @@ UNION ALL
 -- basic btree regular indexes
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_' || c.column_name || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(' || c.column_name || ');' As index
 FROM (SELECT table_name, table_schema  FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE') As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE') As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('countyfp', 'tlid', 'tfidl', 'tfidr', 'tfid', 'zip', 'placefp', 'cousubfp') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -85,7 +85,7 @@ WHERE i.tablename IS NULL AND c.table_schema IN('tiger','tiger_data')  AND (NOT
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_' || c.column_name || '_gist ON ' || c.table_schema || '.' || c.table_name || ' USING gist(' || c.column_name || ');' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE') As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE') As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('the_geom', 'geom') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -96,7 +96,7 @@ WHERE i.tablename IS NULL AND c.table_schema IN('tiger','tiger_data')
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_snd_' || c.column_name || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(soundex(' || c.column_name || '));' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE') As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE') As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('name', 'place', 'city') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -109,7 +109,7 @@ WHERE i.tablename IS NULL AND c.table_schema IN('tiger','tiger_data')
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_lower_' || c.column_name || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(lower(' || c.column_name || '));' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE') As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE') As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('name', 'place', 'city') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -121,7 +121,7 @@ WHERE i.tablename IS NULL AND c.table_schema IN('tiger','tiger_data')
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_least_address' || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(least_hn(fromhn, tohn));' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name LIKE '%addr' AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE' AND table_name LIKE '%addr' AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('fromhn') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -132,7 +132,7 @@ WHERE i.tablename IS NULL
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_l' || c.column_name || '_var_ops' || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(lower(' || c.column_name || ') varchar_pattern_ops);' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE' AND (table_name LIKE '%featnames' or table_name LIKE '%place' or table_name LIKE '%zip_lookup_base' or table_name LIKE '%zip_state_loc') AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE' AND (table_name LIKE '%featnames' or table_name LIKE '%place' or table_name LIKE '%zip_lookup_base' or table_name LIKE '%zip_state_loc') AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('name', 'city', 'place', 'fullname') ) AS c
 		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
@@ -154,11 +154,11 @@ WHERE i.tablename IS NULL **/
 UNION ALL
 SELECT 'CREATE INDEX idx_' || c.table_schema || '_' || c.table_name || '_' || c.column_name || ' ON ' || c.table_schema || '.' || c.table_name || ' USING btree(' || c.column_name || ' );' As index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE' AND table_name LIKE '%edges' AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
+	information_schema.tables WHERE table_type  OPERATOR(pg_catalog.=) 'BASE TABLE' AND table_name LIKE '%edges' AND table_schema IN('tiger','tiger_data')) As t  INNER JOIN
 	(SELECT * FROM information_schema.columns WHERE column_name IN('zipl', 'zipr') ) AS c
-		ON (t.table_name = c.table_name AND t.table_schema = c.table_schema)
+		ON (t.table_name OPERATOR(pg_catalog.=) c.table_name AND t.table_schema  OPERATOR(pg_catalog.=) c.table_schema)
 		LEFT JOIN pg_catalog.pg_indexes i ON
-			(i.tablename = c.table_name AND i.schemaname = c.table_schema
+			(i.tablename OPERATOR(pg_catalog.=) c.table_name AND i.schemaname OPERATOR(pg_catalog.=) c.table_schema
 				AND  indexdef LIKE '%btree%(' || c.column_name || '%)%')
 WHERE i.tablename IS NULL
 
@@ -226,7 +226,7 @@ DROP TABLE dup;
 CREATE INDEX idx_' || t.table_schema || '_' || t.table_name || '_tlid ' || ' ON ' || t.table_schema || '.' || t.table_name || ' USING btree(tlid);
 ' As drop_sql_create_index
 FROM (SELECT table_name, table_schema FROM
-	information_schema.tables WHERE table_type = 'BASE TABLE' AND (table_name LIKE '%featnames' ) AND table_schema IN('tiger','tiger_data')) As t
+	information_schema.tables WHERE table_type OPERATOR(pg_catalog.=) 'BASE TABLE' AND (table_name LIKE '%featnames' ) AND table_schema IN('tiger','tiger_data')) As t
 		LEFT JOIN pg_catalog.pg_indexes i ON
 			(i.tablename = t.table_name AND i.schemaname = t.table_schema
 				AND  indexdef LIKE '%btree%(%tlid%')


=====================================
extras/tiger_geocoder/pagc_normalize/pagc_tables.sql
=====================================
@@ -8,35 +8,35 @@ $$
 DECLARE var_temp text;
 BEGIN
 	var_temp := tiger.SetSearchPathForInstall('tiger'); /** set set search path to have tiger in front **/
-	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema = 'tiger' AND table_name = 'pagc_gaz')  THEN
+	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema OPERATOR(pg_catalog.=) 'tiger' AND table_name OPERATOR(pg_catalog.=) 'pagc_gaz')  THEN
 		CREATE TABLE pagc_gaz (id serial NOT NULL primary key ,seq integer ,word text, stdword text, token integer,is_custom boolean NOT NULL default true);
 		GRANT SELECT ON pagc_gaz TO public;
 	ELSE
 		-- Insist on invoking Postgres logic of owning table by extension. This prevent attacks like CVE-2022-2625.
 		CREATE TABLE IF NOT EXISTS pagc_gaz (id serial NOT NULL primary key ,seq integer ,word text, stdword text, token integer,is_custom boolean NOT NULL default true);
 	END IF;
-	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema = 'tiger' AND table_name = 'pagc_lex')  THEN
+	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema OPERATOR(pg_catalog.=) 'tiger' AND table_name OPERATOR(pg_catalog.=) 'pagc_lex')  THEN
 		CREATE TABLE pagc_lex (id serial NOT NULL primary key,seq integer,word text,stdword text,token integer,is_custom boolean NOT NULL default true);
 		GRANT SELECT ON pagc_lex TO public;
 	ELSE
 		-- Same as above.
 		CREATE TABLE IF NOT EXISTS pagc_lex (id serial NOT NULL primary key,seq integer,word text,stdword text,token integer,is_custom boolean NOT NULL default true);
 	END IF;
-	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema = 'tiger' AND table_name = 'pagc_rules')  THEN
+	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema OPERATOR(pg_catalog.=) 'tiger' AND table_name OPERATOR(pg_catalog.=) 'pagc_rules')  THEN
 		CREATE TABLE pagc_rules (id serial NOT NULL primary key,rule text, is_custom boolean DEFAULT true);
 		GRANT SELECT ON pagc_rules TO public;
 	ELSE
 		-- Same as above.
 		CREATE TABLE IF NOT EXISTS pagc_rules (id serial NOT NULL primary key,rule text, is_custom boolean DEFAULT true);
 	END IF;
-	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema = 'tiger' AND table_name = 'pagc_gaz' AND data_type='text')  THEN
+	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema OPERATOR(pg_catalog.=) 'tiger' AND table_name OPERATOR(pg_catalog.=) 'pagc_gaz' AND data_type OPERATOR(pg_catalog.=) 'text')  THEN
 	-- its probably old table structure change type of lex and gaz columns
 		ALTER TABLE tiger.pagc_lex ALTER COLUMN word TYPE text;
 		ALTER TABLE tiger.pagc_lex ALTER COLUMN stdword TYPE text;
 		ALTER TABLE tiger.pagc_gaz ALTER COLUMN word TYPE text;
 		ALTER TABLE tiger.pagc_gaz ALTER COLUMN stdword TYPE text;
 	END IF;
-	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema = 'tiger' AND table_name = 'pagc_rules' AND column_name = 'is_custom' )  THEN
+	IF NOT EXISTS(SELECT table_name FROM information_schema.columns WHERE table_schema OPERATOR(pg_catalog.=) 'tiger' AND table_name OPERATOR(pg_catalog.=) 'pagc_rules' AND column_name OPERATOR(pg_catalog.=) 'is_custom' )  THEN
 	-- its probably old table structure add column
 		ALTER TABLE tiger.pagc_rules ADD COLUMN is_custom boolean NOT NULL DEFAULT false;
 	END IF;
@@ -8193,4 +8193,4 @@ UPDATE tiger.pagc_rules SET is_custom = false where id < 10000;
 -- after insert we need to set back to true so all
 -- user inputs are treated as custom
 ALTER TABLE tiger.pagc_rules ALTER COLUMN is_custom SET DEFAULT true;
-SELECT pg_catalog.setval('pagc_rules_id_seq', 10000, true);
\ No newline at end of file
+SELECT pg_catalog.setval('pagc_rules_id_seq', 10000, true);


=====================================
liblwgeom/liblwgeom.h.in
=====================================
@@ -1811,6 +1811,10 @@ extern double lwgeom_area_spheroid(const LWGEOM *lwgeom, const SPHEROID *spheroi
 */
 extern double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s);
 
+/**
+* Calculate the geodetic perimeter of a lwgeom on the unit sphere.
+*/
+extern double lwgeom_perimeter_spheroid(const LWGEOM *geom, const SPHEROID *s);
 /**
 * Calculate covers predicate for two lwgeoms on the sphere. Currently
 * only handles point-in-polygon.


=====================================
liblwgeom/lwgeodetic.c
=====================================
@@ -3150,26 +3150,59 @@ double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s)
 
 	assert(geom);
 
-	/* No area in nothing */
+	/* No length in nothing */
 	if ( lwgeom_is_empty(geom) )
 		return 0.0;
 
 	type = geom->type;
 
-	if ( type == POINTTYPE || type == MULTIPOINTTYPE )
+	if ( type == POINTTYPE || type == MULTIPOINTTYPE ||
+	     type == POLYGONTYPE || type == MULTIPOLYGONTYPE ||
+	     type == TRIANGLETYPE || type == TINTYPE ||
+	     type == POLYHEDRALSURFACETYPE || type == CURVEPOLYTYPE ||
+	     type == MULTISURFACETYPE )
 		return 0.0;
 
 	if ( type == LINETYPE )
 		return ptarray_length_spheroid(((LWLINE*)geom)->points, s);
 
+	if ( lwtype_is_collection( type ) )
+	{
+		LWCOLLECTION *col = (LWCOLLECTION*)geom;
+
+		for ( i = 0; i < col->ngeoms; i++ )
+		{
+			length += lwgeom_length_spheroid(col->geoms[i], s);
+		}
+		return length;
+	}
+
+	lwerror("unsupported type passed to lwgeom_length_spheroid");
+	return 0.0;
+}
+
+double lwgeom_perimeter_spheroid(const LWGEOM *geom, const SPHEROID *s)
+{
+	int type;
+	uint32_t i = 0;
+	double perimeter = 0.0;
+
+	assert(geom);
+
+	/* No perimeter in nothing */
+	if ( lwgeom_is_empty(geom) )
+		return 0.0;
+
+	type = geom->type;
+
 	if ( type == POLYGONTYPE )
 	{
 		LWPOLY *poly = (LWPOLY*)geom;
 		for ( i = 0; i < poly->nrings; i++ )
 		{
-			length += ptarray_length_spheroid(poly->rings[i], s);
+			perimeter += ptarray_length_spheroid(poly->rings[i], s);
 		}
-		return length;
+		return perimeter;
 	}
 
 	if ( type == TRIANGLETYPE )
@@ -3181,12 +3214,11 @@ double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s)
 
 		for ( i = 0; i < col->ngeoms; i++ )
 		{
-			length += lwgeom_length_spheroid(col->geoms[i], s);
+			perimeter += lwgeom_perimeter_spheroid(col->geoms[i], s);
 		}
-		return length;
+		return perimeter;
 	}
 
-	lwerror("unsupported type passed to lwgeom_length_sphere");
 	return 0.0;
 }
 


=====================================
liblwgeom/lwgeom_geos_split.c
=====================================
@@ -282,9 +282,12 @@ lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in,
 
 	LWDEBUGF(3, "Projected point:(%.15g %.15g), seg:%d, p1:(%.15g %.15g), p2:(%.15g %.15g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y);
 
-	/* When closest point == an endpoint, this is a boundary intersection */
-	if ( ( (seg == nsegs-1) && P4D_SAME_STRICT(&pt_projected, &p2) ) ||
-	     ( (seg == 0)       && P4D_SAME_STRICT(&pt_projected, &p1) ) )
+	/* When closest point == an endpoint, this is a boundary intersection.
+	 * Compare only X and Y since pt_projected.x/y were forced to pt.x/y above,
+	 * and Z/M may be NaN when line coordinates are very large (causing Inf/Inf
+	 * in closest_point_on_segment). See #5916. */
+	if ( ( (seg == nsegs-1) && (pt_projected.x == p2.x) && (pt_projected.y == p2.y) ) ||
+	     ( (seg == 0)       && (pt_projected.x == p1.x) && (pt_projected.y == p1.y) ) )
 	{
 		return 1;
 	}


=====================================
libpgcommon/lwgeom_transform.c
=====================================
@@ -17,8 +17,6 @@
 #include "miscadmin.h"
 #include "utils/memutils.h"
 #include "executor/spi.h"
-#include "access/hash.h"
-#include "utils/hsearch.h"
 
 /* PostGIS headers */
 #include "../postgis_config.h"
@@ -176,6 +174,40 @@ GetProjStringsSPI(int32_t srid)
 		elog(ERROR, "Could not connect to database using SPI");
 	}
 
+	/*
+	 * During pg_upgrade, geography typmod is parsed before spatial_ref_sys
+	 * exists or is populated. Check both conditions via catalog before
+	 * querying the table, to avoid a transaction-aborting error.
+	 * If either check fails, return "EPSG:<srid>" directly so PROJ can
+	 * resolve standard codes from its own database.
+	 */
+	Oid nsp_oid = POSTGIS_CONSTANTS ? POSTGIS_CONSTANTS->install_nsp_oid : InvalidOid;
+	snprintf(proj_spi_buffer, spibufferlen,
+	         "SELECT 1 FROM pg_class "
+	         "WHERE relname = 'spatial_ref_sys' AND relnamespace = %u",
+	         nsp_oid);
+	spi_result = SPI_execute(proj_spi_buffer, true, 1);
+	bool srs_exists = (spi_result == SPI_OK_SELECT && SPI_processed > 0);
+
+	bool srs_populated = false;
+	if (srs_exists)
+	{
+		snprintf(proj_spi_buffer, spibufferlen,
+		         "SELECT 1 FROM %s LIMIT 1",
+		         postgis_spatial_ref_sys());
+		spi_result = SPI_execute(proj_spi_buffer, true, 1);
+		srs_populated = (spi_result == SPI_OK_SELECT && SPI_processed > 0);
+	}
+
+	if (!srs_exists || !srs_populated)
+	{
+		char tmp[maxprojlen];
+		snprintf(tmp, maxprojlen, "EPSG:%d", srid);
+		strs.authtext = SPI_pstrdup(tmp);
+		SPI_finish();
+		return strs;
+	}
+
 	static char *proj_str_tmpl =
 	    "SELECT proj4text, auth_name, auth_srid, srtext "
 	    "FROM %s "


=====================================
postgis/flatgeobuf.c
=====================================
@@ -287,8 +287,6 @@ static void decode_properties(struct flatgeobuf_decode_ctx *ctx, Datum *values,
 
 	POSTGIS_DEBUGF(3, "flatgeobuf: decode_properties from byte array with length %d at offset %d", size, offset);
 
-	// TODO: init isnull
-
 	if (size > 0 && size < (sizeof(uint16_t) + sizeof(uint8_t)))
 		elog(ERROR, "flatgeobuf: decode_properties: Unexpected properties data size %d", size);
 	while (offset + 1 < size) {
@@ -389,7 +387,10 @@ static void decode_properties(struct flatgeobuf_decode_ctx *ctx, Datum *values,
 			if (offset + sizeof(float) > size)
 				elog(ERROR, "flatgeobuf: decode_properties: Invalid size for float value");
 			memcpy(&value, data + offset, sizeof(float));
-			values[ci] = Float4GetDatum(value);
+			if (getBaseType(TupleDescAttr(ctx->tupdesc, ci)->atttypid) == FLOAT8OID)
+				values[ci] = Float8GetDatum((double) value);
+			else
+				values[ci] = Float4GetDatum(value);
 			offset += sizeof(float);
 			break;
 		}
@@ -467,7 +468,9 @@ void flatgeobuf_decode_row(struct flatgeobuf_decode_ctx *ctx)
 	uint32_t natts = ctx->tupdesc->natts;
 
 	Datum *values = palloc0(natts * sizeof(Datum));
-	bool *isnull = palloc0(natts * sizeof(bool));
+	bool *isnull = palloc(natts * sizeof(bool));
+	for (uint32_t j = 0; j < natts; j++) isnull[j] = true;
+	isnull[0] = false;
 
 	values[0] = Int32GetDatum(ctx->fid);
 
@@ -476,6 +479,7 @@ void flatgeobuf_decode_row(struct flatgeobuf_decode_ctx *ctx)
 
 	if (ctx->ctx->lwgeom != NULL) {
 		values[1] = PointerGetDatum(geometry_serialize(ctx->ctx->lwgeom));
+		isnull[1] = false;
 	} else {
 		POSTGIS_DEBUG(3, "geometry is null");
 		isnull[1] = true;


=====================================
postgis/geography_measurement.c
=====================================
@@ -599,12 +599,12 @@ Datum geography_perimeter(PG_FUNCTION_ARGS)
 		s.a = s.b = s.radius;
 
 	/* Calculate the length */
-	length = lwgeom_length_spheroid(lwgeom, &s);
+	length = lwgeom_perimeter_spheroid(lwgeom, &s);
 
 	/* Something went wrong... */
 	if ( length < 0.0 )
 	{
-		elog(ERROR, "lwgeom_length_spheroid returned length < 0.0");
+		elog(ERROR, "lwgeom_perimeter_spheroid returned length < 0.0");
 		PG_RETURN_NULL();
 	}
 


=====================================
postgis/lwgeom_geos_prepared.h
=====================================
@@ -27,7 +27,6 @@
 #include "postgres.h"
 #include "fmgr.h"
 #include "miscadmin.h"
-#include "utils/hsearch.h"
 #include "utils/memutils.h"
 #include "access/hash.h"
 


=====================================
postgis/lwgeom_in_flatgeobuf.c
=====================================
@@ -67,6 +67,60 @@ static char *get_pgtype(uint8_t column_type) {
 	elog(ERROR, "unknown column_type %d", column_type);
 }
 
+static const char *
+flatgeobuf_type_name(uint8_t fgb_type)
+{
+	/* Names match FlatGeobuf::EnumNamesColumnType() in header_generated.h */
+	static const char * const names[] = {
+		"Byte", "UByte", "Bool", "Short", "UShort",
+		"Int", "UInt", "Long", "ULong",
+		"Float", "Double", "String", "Json", "DateTime", "Binary"
+	};
+	if (fgb_type >= sizeof(names) / sizeof(names[0]))
+		return "unknown";
+	return names[fgb_type];
+}
+
+static bool
+flatgeobuf_type_compatible(uint8_t fgb_type, Oid pgtype)
+{
+	switch (fgb_type)
+	{
+	case flatgeobuf_column_type_bool:
+		return pgtype == BOOLOID;
+	/* small integer types: allow widening into larger signed ints */
+	case flatgeobuf_column_type_byte:
+	case flatgeobuf_column_type_ubyte:
+	case flatgeobuf_column_type_short:
+	case flatgeobuf_column_type_ushort:
+		return pgtype == INT2OID || pgtype == INT4OID || pgtype == INT8OID;
+	/* int32: allow widening to bigint */
+	case flatgeobuf_column_type_int:
+		return pgtype == INT4OID || pgtype == INT8OID;
+	/* uint32 max exceeds INT4, must land in bigint */
+	case flatgeobuf_column_type_uint:
+		return pgtype == INT8OID;
+	case flatgeobuf_column_type_long:
+	case flatgeobuf_column_type_ulong:
+		return pgtype == INT8OID;
+	/* float: allow widening to double (explicit conversion handled in decode) */
+	case flatgeobuf_column_type_float:
+		return pgtype == FLOAT4OID || pgtype == FLOAT8OID;
+	case flatgeobuf_column_type_double:
+		return pgtype == FLOAT8OID;
+	case flatgeobuf_column_type_string:
+		return pgtype == TEXTOID || pgtype == VARCHAROID;
+	case flatgeobuf_column_type_datetime:
+		return pgtype == DATEOID || pgtype == TIMEOID ||
+		       pgtype == TIMESTAMPOID || pgtype == TIMESTAMPTZOID;
+	case flatgeobuf_column_type_json:
+		return pgtype == JSONBOID;
+	case flatgeobuf_column_type_binary:
+		return pgtype == BYTEAOID;
+	}
+	return false;
+}
+
 PG_FUNCTION_INFO_V1(pgis_tablefromflatgeobuf);
 Datum pgis_tablefromflatgeobuf(PG_FUNCTION_ARGS)
 {
@@ -191,7 +245,29 @@ Datum pgis_fromflatgeobuf(PG_FUNCTION_ARGS)
 			SRF_RETURN_DONE(funcctx);
 		}
 
-		// TODO: get table and verify structure against header
+		/* Validate that the file schema matches the caller-supplied composite type.
+		 * tupdesc positions 0 (fid) and 1 (geom) are fixed; file columns start at 2. */
+		if (ctx->ctx->columns_size != (uint32_t)(tupdesc->natts - 2))
+			ereport(ERROR,
+				(errcode(ERRCODE_DATATYPE_MISMATCH),
+				 errmsg("flatgeobuf: column count mismatch: "
+				        "file has %u columns, target type has %d",
+				        ctx->ctx->columns_size, tupdesc->natts - 2)));
+
+		for (uint16_t col_i = 0; col_i < ctx->ctx->columns_size; col_i++)
+		{
+			flatgeobuf_column *col = ctx->ctx->columns[col_i];
+			Oid pgtype = getBaseType(TupleDescAttr(tupdesc, col_i + 2)->atttypid);
+			if (!flatgeobuf_type_compatible(col->type, pgtype))
+				ereport(ERROR,
+					(errcode(ERRCODE_DATATYPE_MISMATCH),
+					 errmsg("flatgeobuf: column \"%s\" type mismatch: "
+					        "file type \"%s\" is not compatible with PostgreSQL type %s",
+					        col->name,
+					        flatgeobuf_type_name(col->type),
+					        format_type_be(pgtype))));
+		}
+
 		MemoryContextSwitchTo(oldcontext);
 	}
 


=====================================
postgis/lwgeom_spheroid.c
=====================================
@@ -370,7 +370,7 @@ Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS)
 		PG_RETURN_FLOAT8(0.0);
 	}
 
-	length = lwgeom_length_spheroid(lwgeom, sphere);
+	length = lwgeom_length_spheroid(lwgeom, sphere) + lwgeom_perimeter_spheroid(lwgeom, sphere);
 	lwgeom_free(lwgeom);
 	PG_FREE_IF_COPY(geom, 0);
 


=====================================
postgis_revision.h
=====================================
@@ -1 +1 @@
-#define POSTGIS_REVISION 3d12666
+#define POSTGIS_REVISION 94d984b


=====================================
regress/core/geography.sql
=====================================
@@ -149,6 +149,10 @@ SELECT 'lrs_llp_4', round(ST_LineLocatePoint(geography 'linestring(0 1, 50 1)',
 
 SELECT 'lrs_substr_1', ST_AsText(ST_LineSubstring(geography 'linestring(0 20, 100 20)', 0.1, 0.2),2);
 
+-- Ticket #6076
+SELECT 'ticket_6076_length', round(ST_Length(ST_GeogFromText('GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 0 1), POLYGON ((0 0, 0 1, 1 0, 0 0)))'))::numeric, 3);
+SELECT 'ticket_6076_perimeter', round(ST_Perimeter(ST_GeogFromText('GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 0 1), POLYGON ((0 0, 0 1, 1 0, 0 0)))'))::numeric, 3);
+
 --SELECT 'lrs_cp_1', ST_AsText(ST_ClosestPoint(geography 'Linestring(0 20, 50 20)', 'Point(25 20)'), 3);
 --SELECT 'lrs_cp_2', ST_AsText(ST_ClosestPoint(geography 'Point(25 20)', geography 'Linestring(0 20, 50 20)'), 3);
 


=====================================
regress/core/geography_expected
=====================================
@@ -66,4 +66,6 @@ lrs_llp_2|0.00
 lrs_llp_3|1.00
 ERROR:  geography_line_locate_point: 2nd arg is not a point
 lrs_substr_1|LINESTRING(9.28 23.25,18.97 25.93)
+ticket_6076_length|110574.389
+ticket_6076_perimeter|378793.448
 lrs_sl_1|LINESTRING(25 42.79,25 40)


=====================================
sfcgal/lwgeom_sfcgal.c
=====================================
@@ -319,7 +319,11 @@ sfcgal_tesselate(PG_FUNCTION_ARGS)
 	geom = POSTGIS2SFCGALGeometry(input);
 	PG_FREE_IF_COPY(input, 0);
 
+#if POSTGIS_SFCGAL_VERSION < 20300
 	result = sfcgal_geometry_tesselate(geom);
+#else
+        result = sfcgal_geometry_tessellate(geom);
+#endif
 	sfcgal_geometry_delete(geom);
 
 	output = SFCGALGeometry2POSTGIS(result, 0, srid);



View it on GitLab: https://salsa.debian.org/debian-gis-team/postgis/-/commit/982f263cc49c0835624ec12c157d7aba76eb8d21

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/postgis/-/commit/982f263cc49c0835624ec12c157d7aba76eb8d21
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260609/bcf38421/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list