From 0e0ceb96cd962edd568bf8193a788786a583b39d Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Thu, 16 Apr 2026 06:55:28 -0400 Subject: [PATCH] import CS postgis-3.6.1-1.module_el9+1300+1c4aa8df --- .fmf/version | 1 - .gitignore | 52 +- .postgis.metadata | 1 + postgis.spec => SPECS/postgis.spec | 29 +- ci.fmf | 1 - gating.yaml | 7 - plans/tier1-public.fmf | 8 - postgis-c99-2.patch | 17 - postgis-c99.patch | 54 - postgis2-proj8.patch | 3227 ---------------------------- sources | 2 - 11 files changed, 22 insertions(+), 3377 deletions(-) delete mode 100644 .fmf/version create mode 100644 .postgis.metadata rename postgis.spec => SPECS/postgis.spec (98%) delete mode 100644 ci.fmf delete mode 100644 gating.yaml delete mode 100644 plans/tier1-public.fmf delete mode 100644 postgis-c99-2.patch delete mode 100644 postgis-c99.patch delete mode 100644 postgis2-proj8.patch delete mode 100644 sources diff --git a/.fmf/version b/.fmf/version deleted file mode 100644 index d00491f..0000000 --- a/.fmf/version +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/.gitignore b/.gitignore index dd88dc6..fc963d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,51 +1 @@ -/postgis-2.5.3.tar.gz -/postgis-3.0.0.pdf -/postgis-3.0.0.tar.gz -/postgis-3.0.1.tar.gz -/postgis-3.0.1.pdf -/postgis-2.5.4.tar.gz -/postgis-3.0.2.pdf -/postgis-3.0.2.tar.gz -/postgis-2.5.5.tar.gz -/postgis-3.0.3.tar.gz -/postgis-3.0.3.pdf -/postgis-3.1.0.pdf -/postgis-3.1.0.tar.gz -/postgis-3.1.1.tar.gz -/postgis-3.1.1.pdf -/postgis-3.1.2.tar.gz -/postgis-3.1.2.pdf -/postgis-3.1.3.pdf -/postgis-3.1.3.tar.gz -/postgis-3.1.4.pdf -/postgis-3.1.4.tar.gz -/postgis-3.2.0.pdf -/postgis-3.2.0.tar.gz -/postgis-3.2.1.pdf -/postgis-3.2.1.tar.gz -/postgis-3.2.2.tar.gz -/postgis-3.2.2.pdf -/postgis-3.3.1.tar.gz -/postgis-3.3.1.pdf -/postgis-3.3.2.tar.gz -/postgis-3.3.2.pdf -/postgis-3.3.3.pdf -/postgis-3.3.3.tar.gz -/postgis-3.3.4.pdf -/postgis-3.3.4.tar.gz -/postgis-3.4.0-en.pdf -/postgis-3.4.0.tar.gz -/postgis-3.4.1.tar.gz -/postgis-3.4.1-en.pdf -/postgis-3.4.2-en.pdf -/postgis-3.4.2.tar.gz -/postgis-3.4.3-en.pdf -/postgis-3.4.3.tar.gz -/postgis-3.5.0-en.pdf -/postgis-3.5.0.tar.gz -/postgis-3.5.1-en.pdf -/postgis-3.5.1.tar.gz -/postgis-3.5.2-en.pdf -/postgis-3.5.2.tar.gz -/postgis-3.5.3-en.pdf -/postgis-3.5.3.tar.gz +SOURCES/postgis-3.6.1.tar.gz diff --git a/.postgis.metadata b/.postgis.metadata new file mode 100644 index 0000000..9e5fcce --- /dev/null +++ b/.postgis.metadata @@ -0,0 +1 @@ +d560ab14fee5af4bc7e554b2ec45d4ce4a6ce0cf SOURCES/postgis-3.6.1.tar.gz diff --git a/postgis.spec b/SPECS/postgis.spec similarity index 98% rename from postgis.spec rename to SPECS/postgis.spec index a74ac73..fe78570 100644 --- a/postgis.spec +++ b/SPECS/postgis.spec @@ -5,10 +5,11 @@ %{!?upgrade_prev:%global upgrade_prev 0} %{!?runselftest:%global runselftest 1} %{!?llvmjit:%global llvmjit 0} +%{!?raster:%global raster 0} %global __requires_exclude ^perl\\(Pg\\)$ -%global majorversion 3.5 +%global majorversion 3.6 %global soversion 3 %global prevmajorversion 2.5 %global prevversion %{prevmajorversion}.5 @@ -18,14 +19,13 @@ %global __provides_exclude_from %{_libdir}/pgsql Name: postgis -Version: 3.5.3 -Release: 5%{?dist} +Version: 3.6.1 +Release: 1%{?dist} Summary: Geographic Information Systems Extensions to PostgreSQL License: GPL-2.0-or-later URL: https://www.postgis.net Source0: https://download.osgeo.org/%{name}/source/%{name}-%{version}.tar.gz -Source2: https://download.osgeo.org/%{name}/docs/%{name}-%{version}-en.pdf %if %upgrade_prev Source3: https://download.osgeo.org/%{name}/source/%{name}-%{prevversion}.tar.gz @@ -61,7 +61,8 @@ BuildRequires: perl-generators BuildRequires: postgresql-server-devel BuildRequires: proj-devel >= 5.2.0 BuildRequires: protobuf-c-devel - +BuildRequires: CUnit-devel +BuildRequires: perl-Time-HiRes %if %upgrade BuildRequires: postgresql-upgrade-devel %endif @@ -189,11 +190,13 @@ cd %{name}-%{prevversion} %endif ) %endif -cp -p %{SOURCE2} . %build %configure %configure_opts --with-pgconfig=%{_bindir}/pg_server_config \ +%if ! %raster + --without-raster \ +%endif %if %llvmjit --with-llvm \ %endif @@ -364,13 +367,17 @@ fi %{_datadir}/pgsql/extension/address_standardizer*.sql %{_datadir}/pgsql/extension/address_standardizer*.control %{_datadir}/pgsql/extension/postgis-*.sql +%if %raster %{_datadir}/pgsql/extension/postgis_raster*.sql +%endif %if 0%{?fedora} %{_datadir}/pgsql/extension/postgis_sfcgal*.sql %endif %{_datadir}/pgsql/extension/postgis_topology*.sql %{_datadir}/pgsql/extension/postgis.control +%if %raster %{_datadir}/pgsql/extension/postgis_raster.control +%endif %if 0%{?fedora} %{_datadir}/pgsql/extension/postgis_sfcgal.control %endif @@ -383,7 +390,9 @@ fi %{_datadir}/postgis/create_uninstall.pl %{_datadir}/postgis/repo_revision.pl %{_libdir}/pgsql/address_standardizer-%{soversion}.so +%if %raster %{_libdir}/pgsql/postgis_raster-%{soversion}.so +%endif %if 0%{?fedora} %{_libdir}/pgsql/postgis_sfcgal-%{soversion}.so %endif @@ -393,7 +402,9 @@ fi %{_bindir}/postgis %{_bindir}/postgis_restore %{_bindir}/pgsql2shp +%if %raster %{_bindir}/raster2pgsql +%endif %{_bindir}/shp2pgsql %{_bindir}/pgtopo_export %{_bindir}/pgtopo_import @@ -468,12 +479,12 @@ fi %files docs -%doc postgis*.pdf %changelog -* Tue Nov 18 2025 Nikola Davidova - 3.5.3-5 -- Rebuild for adding tmt metadata +* Tue Nov 18 2025 Filip Janus - 3.6.1-1 +- Update to 3.6.1 +- Initial import for postgresql18 * Wed Nov 12 2025 Nikola Davidova - 3.5.3-4 - Avoid perl(Pg) dependency on RHEL, diff --git a/ci.fmf b/ci.fmf deleted file mode 100644 index c5aa0e0..0000000 --- a/ci.fmf +++ /dev/null @@ -1 +0,0 @@ -resultsdb-testcase: separate diff --git a/gating.yaml b/gating.yaml deleted file mode 100644 index cbfd0ef..0000000 --- a/gating.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# RHEL ---- !Policy -product_versions: - - rhel-* -decision_context: osci_compose_gate -rules: - - !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-public.functional} diff --git a/plans/tier1-public.fmf b/plans/tier1-public.fmf deleted file mode 100644 index d510d29..0000000 --- a/plans/tier1-public.fmf +++ /dev/null @@ -1,8 +0,0 @@ -summary: Public Tier1 tests plan -discover: - how: fmf - filter: 'tier: 1' - url: https://gitlab.com/redhat/centos-stream/tests/postgis -execute: - how: tmt - diff --git a/postgis-c99-2.patch b/postgis-c99-2.patch deleted file mode 100644 index 457bfce..0000000 --- a/postgis-c99-2.patch +++ /dev/null @@ -1,17 +0,0 @@ -Include for isnan. This avoids an implicit function -declaration and a build failure with future compilers. - -Submitted upstream: - -diff -ur postgis-3.3.2.orig/loader/shp2pgsql-core.c postgis-3.3.2/loader/shp2pgsql-core.c ---- postgis-3.3.2.orig/loader/shp2pgsql-core.c 2022-11-13 08:09:23.000000000 +0100 -+++ postgis-3.3.2/loader/shp2pgsql-core.c 2023-04-09 22:01:46.377934865 +0200 -@@ -15,6 +15,8 @@ - - #include "../postgis_config.h" - -+#include /* for isnan */ -+ - #include "shp2pgsql-core.h" - #include "../liblwgeom/liblwgeom.h" - #include "../liblwgeom/lwgeom_log.h" /* for LWDEBUG macros */ diff --git a/postgis-c99.patch b/postgis-c99.patch deleted file mode 100644 index cfc363a..0000000 --- a/postgis-c99.patch +++ /dev/null @@ -1,54 +0,0 @@ -commit ae53a53246ccb26a6e82fede1a4184b41bcf097d -Author: Regina Obe -Date: Sat Feb 19 00:21:01 2022 -0500 - - Fix PG 15 building atoi removed. References #5100 for PostGIS 3.3.0 - -diff -ur postgis-3.3.2.orig/postgis-2.5.5/postgis/gserialized_typmod.c postgis-3.3.2/postgis-2.5.5/postgis/gserialized_typmod.c ---- postgis-3.3.2.orig/postgis-2.5.5/postgis/gserialized_typmod.c 2023-04-09 21:52:47.909294055 +0200 -+++ postgis-3.3.2/postgis-2.5.5/postgis/gserialized_typmod.c 2023-04-09 21:55:24.744826310 +0200 -@@ -35,7 +35,7 @@ - - #include "utils/elog.h" - #include "utils/array.h" --#include "utils/builtins.h" /* for pg_atoi */ -+#include "utils/builtins.h" /* for cstring_to_text */ - #include "lib/stringinfo.h" /* For binary input */ - #include "catalog/pg_type.h" /* for CSTRINGOID */ - -@@ -267,8 +267,33 @@ - } - if ( i == 1 ) /* SRID */ - { -- int srid = pg_atoi(DatumGetCString(elem_values[i]), -- sizeof(int32), '\0'); -+ char *int_string = DatumGetCString(elem_values[i]); -+ char *endp; -+ long l; -+ int32_t srid; -+ -+ errno = 0; -+ l = strtol(int_string, &endp, 10); -+ -+ if (int_string == endp) -+ ereport(ERROR, -+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), -+ errmsg("invalid input syntax for type %s: \"%s\"", -+ "integer", int_string))); -+ -+ if (errno == ERANGE || l < INT_MIN || l > INT_MAX) -+ ereport(ERROR, -+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), -+ errmsg("value \"%s\" is out of range for type %s", int_string, -+ "integer"))); -+ -+ if (*endp != '\0') -+ ereport(ERROR, -+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), -+ errmsg("invalid input syntax for type %s: \"%s\"", -+ "integer", int_string))); -+ -+ srid = clamp_srid(l); - srid = clamp_srid(srid); - POSTGIS_DEBUGF(3, "srid: %d", srid); - if ( srid != SRID_UNKNOWN ) diff --git a/postgis2-proj8.patch b/postgis2-proj8.patch deleted file mode 100644 index b4d9214..0000000 --- a/postgis2-proj8.patch +++ /dev/null @@ -1,3227 +0,0 @@ -diff -rupN postgis-2.5.5/autogen.sh postgis-2.5.5-new/autogen.sh ---- postgis-2.5.5/autogen.sh 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/autogen.sh 2022-08-06 12:13:08.260741405 +0200 -@@ -81,6 +81,9 @@ ${ACLOCAL} -I macros || giveup - echo "* Running ${AUTOCONF} (${AUTOCONF_VER})" - ${AUTOCONF} || giveup - -+# Work around an autoconf bug insisting in having this file -+touch build-aux/config.rpath -+ - if test -f "${PWD}/configure"; then - echo "======================================" - echo "Now you are ready to run './configure'" -diff -rupN postgis-2.5.5/configure.ac postgis-2.5.5-new/configure.ac ---- postgis-2.5.5/configure.ac 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/configure.ac 2022-08-06 12:15:04.877744014 +0200 -@@ -851,42 +851,64 @@ if test ! "x$PROJDIR" = "x"; then - AC_MSG_RESULT([Using user-specified proj directory: $PROJDIR]) - - dnl Add the include directory to PROJ_CPPFLAGS -- PROJ_CPPFLAGS="-I$PROJDIR/include -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H=1" -- PROJ_LDFLAGS="-L$PROJDIR/lib" -+ PROJ_CPPFLAGS="-I$PROJDIR/include" -+ PROJ_LDFLAGS="-L$PROJDIR/lib -lproj" - else - AC_MSG_ERROR([the --with-projdir directory "$PROJDIR" cannot be found]) - fi - fi -+elif test ! -z "$PKG_CONFIG"; then -+ dnl To keep compatibility with PROJ pre 4.8, default to lproj if not found -+ PKG_CHECK_MODULES([PROJ], [proj], -+ [ -+ PROJ_CPPFLAGS="$PROJ_CFLAGS" -+ PROJ_LDFLAGS="$PROJ_LIBS" -+ POSTGIS_PROJ_VERSION=`$PKG_CONFIG proj --modversion | sed 's/\([[0-9]]\).*\([[0-9]]\).*\([[0-9]]\)/\1\2/'` -+ ], -+ [ -+ PROJ_LDFLAGS="-lproj" -+ ]) -+else -+ dnl To keep compatibility with PROJ pre 4.8, default to lproj -+ PROJ_LDFLAGS="-lproj" - fi - -+ - dnl Check that we can find the proj_api.h header file - CPPFLAGS_SAVE="$CPPFLAGS" - CPPFLAGS="$PROJ_CPPFLAGS" --AC_CHECK_HEADER([proj_api.h], [], [AC_MSG_ERROR([could not find proj_api.h - you may need to specify the directory of a PROJ.4 installation using --with-projdir])], --[ --#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1 --]) -- --dnl Return the PROJ.4 version number --AC_PROJ_VERSION([POSTGIS_PROJ_VERSION]) -+AC_CHECK_HEADER([proj_api.h], -+ [], -+ [AC_CHECK_HEADER([proj.h], -+ [], -+ [AC_MSG_ERROR([could not find proj.h or proj_api.h - you may need to specify the directory of a PROJ installation using --with-projdir])] -+ )] -+ ) -+ -+dnl Return the PROJ.4 version number if not detected by pkg-config -+if test "x$POSTGIS_PROJ_VERSION" = "x"; then -+ AC_PROJ_VERSION([POSTGIS_PROJ_VERSION]) -+fi - AC_DEFINE_UNQUOTED([POSTGIS_PROJ_VERSION], [$POSTGIS_PROJ_VERSION], [PROJ library version]) - AC_SUBST([POSTGIS_PROJ_VERSION]) - CPPFLAGS="$CPPFLAGS_SAVE" - -+dnl Ensure that we are using PROJ >= 4.9.0 (requires pj_set_searchpath) -+if test ! "$POSTGIS_PROJ_VERSION" -ge 49; then -+ AC_MSG_ERROR([PostGIS requires PROJ >= 4.9.0]) -+fi -+ - AC_SUBST([PROJ_CPPFLAGS]) - AC_SUBST([PROJ_LDFLAGS]) - --dnl Ensure that we are using PROJ >= 4.6.0 (requires pj_set_searchpath) --if test ! "$POSTGIS_PROJ_VERSION" -ge 46; then -- AC_MSG_ERROR([PostGIS requires PROJ >= 4.6.0]) --fi -- - dnl Ensure we can link against libproj - LIBS_SAVE="$LIBS" - LIBS="$PROJ_LDFLAGS" --AC_CHECK_LIB([proj], [pj_get_release], -- [], -- [AC_MSG_ERROR([could not find libproj - you may need to specify the directory of a PROJ.4 installation using --with-projdir])], -+AC_CHECK_LIB([proj], [pj_get_release], [], -+ [AC_CHECK_LIB([proj], [proj_info], [], -+ [AC_MSG_ERROR([could not find libproj - you may need to specify the directory of a PROJ installation using --with-projdir])], -+ [] -+ )], - []) - LIBS="$LIBS_SAVE" - -diff -rupN postgis-2.5.5/liblwgeom/cunit/cu_geodetic.c postgis-2.5.5-new/liblwgeom/cunit/cu_geodetic.c ---- postgis-2.5.5/liblwgeom/cunit/cu_geodetic.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/cunit/cu_geodetic.c 2022-08-06 11:49:41.821709943 +0200 -@@ -1276,7 +1276,7 @@ static void test_spheroid_distance(void) - { - GEOGRAPHIC_POINT g1, g2; - double d; --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - double epsilon; /* irregular */ - #else - const double epsilon = 1e-8; /* at least 10 nm precision */ -@@ -1291,7 +1291,7 @@ static void test_spheroid_distance(void) - point_set(0.0, 0.0, &g1); - point_set(0.0, 1.0, &g2); - d = spheroid_distance(&g1, &g2, &s); --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - epsilon = 1e-6; - #endif - CU_ASSERT_DOUBLE_EQUAL(d, 110574.3885577987957342, epsilon); -@@ -1301,7 +1301,7 @@ static void test_spheroid_distance(void) - point_set(-10.0, 0.0, &g1); - point_set(0.0, 0.0, &g2); - d = spheroid_distance(&g1, &g2, &s); --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - epsilon = 1e-3; - #endif - CU_ASSERT_DOUBLE_EQUAL(d, 1113194.9079327357264771, epsilon); -@@ -1311,7 +1311,7 @@ static void test_spheroid_distance(void) - point_set(-1.0, 0.0, &g1); - point_set(0.0, 0.0, &g2); - d = spheroid_distance(&g1, &g2, &s); --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - epsilon = 1e-4; - #endif - CU_ASSERT_DOUBLE_EQUAL(d, 111319.4907932735726477, epsilon); -@@ -1321,7 +1321,7 @@ static void test_spheroid_distance(void) - point_set(-180.0, 0.0, &g1); - point_set(0.0, 1.0, &g2); - d = spheroid_distance(&g1, &g2, &s); --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - epsilon = 1e-5; - #endif - CU_ASSERT_DOUBLE_EQUAL(d, 19893357.0700676468277450, epsilon); -@@ -1331,7 +1331,7 @@ static void test_spheroid_distance(void) - point_set(-180.0, 0.0, &g1); - point_set(0.0, 90.0, &g2); - d = spheroid_distance(&g1, &g2, &s); --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - epsilon = 1e-6; - #endif - CU_ASSERT_DOUBLE_EQUAL(d, 10001965.7293127228117396, epsilon); -@@ -1372,7 +1372,7 @@ static void test_spheroid_area(void) - a1 = lwgeom_area_sphere(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a1, 12341436880.106982993974659, 0.1); - /* spheroid: Planimeter -E -p 20 -r --input-string "3 -2;4 -2;4 -1;3 -1" */ --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - // printf("XXXXX %d\n", PJ_VERSION); - a2 = lwgeom_area_spheroid(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a2, 12286884908.946891319597874, 0.1); -@@ -1386,7 +1386,7 @@ static void test_spheroid_area(void) - a1 = lwgeom_area_sphere(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1); - /* spheroid: Planimeter -E -p 20 --input-string "2 8.5;1 8.5;1 9.5;2 9.5" */ --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - a2 = lwgeom_area_spheroid(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1); - #endif -@@ -1399,7 +1399,7 @@ static void test_spheroid_area(void) - a1 = lwgeom_area_sphere(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1); - /* spheroid: Planimeter -E -p 20 -r --input-string "2 179.5;1 179.5;1 178.5;2 178.5" */ --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - a2 = lwgeom_area_spheroid(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1); - #endif -@@ -1412,7 +1412,7 @@ static void test_spheroid_area(void) - a1 = lwgeom_area_sphere(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1); - /* spheroid: Planimeter -E -p 20 --input-string "2 179.5;1 179.5;1 -179.5;2 -179.5" */ --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - a2 = lwgeom_area_spheroid(lwg, &s); - CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1); - #endif -diff -rupN postgis-2.5.5/liblwgeom/cunit/cu_geos_cluster.c postgis-2.5.5-new/liblwgeom/cunit/cu_geos_cluster.c ---- postgis-2.5.5/liblwgeom/cunit/cu_geos_cluster.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/cunit/cu_geos_cluster.c 2022-08-06 11:48:23.729708197 +0200 -@@ -10,6 +10,8 @@ - * - **********************************************************************/ - -+#include -+ - #include "CUnit/Basic.h" - - #include "../lwgeom_log.h" -diff -rupN postgis-2.5.5/liblwgeom/g_box.c postgis-2.5.5-new/liblwgeom/g_box.c ---- postgis-2.5.5/liblwgeom/g_box.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/g_box.c 2022-08-06 11:48:23.730708197 +0200 -@@ -398,11 +398,11 @@ GBOX* gbox_from_string(const char *str) - - char* gbox_to_string(const GBOX *gbox) - { -- static int sz = 138; -+ const size_t sz = 138; - char *str = NULL; - - if ( ! gbox ) -- return strdup("NULL POINTER"); -+ return lwstrdup("NULL POINTER"); - - str = (char*)lwalloc(sz); - -diff -rupN postgis-2.5.5/liblwgeom/liblwgeom.h.in postgis-2.5.5-new/liblwgeom/liblwgeom.h.in ---- postgis-2.5.5/liblwgeom/liblwgeom.h.in 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/liblwgeom.h.in 2022-08-06 12:19:54.803750500 +0200 -@@ -32,15 +32,25 @@ - #include - #include - #include --#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1 -+ -+#include "../postgis_config.h" -+ -+#if POSTGIS_PROJ_VERSION < 60 - #include "proj_api.h" -+typedef struct PJ -+{ -+ projPJ pj_from; -+ projPJ pj_to; -+} PJ; -+#else -+#include "proj.h" -+#endif - --#if defined(PJ_VERSION) && PJ_VERSION >= 490 --/* Enable new geodesic functions */ --#define PROJ_GEODESIC 1 -+#if POSTGIS_PROJ_VERSION < 49 -+#undef PROJ_GEODESIC - #else --/* Use the old (pre-2.2) geodesic functions */ --#define PROJ_GEODESIC 0 -+/* Enable new geodesic functions API */ -+#define PROJ_GEODESIC - #endif - - /** -@@ -82,13 +92,13 @@ const char* lwgeom_version(void); - /** - * LWTYPE numbers, used internally by PostGIS - */ --#define POINTTYPE 1 --#define LINETYPE 2 --#define POLYGONTYPE 3 --#define MULTIPOINTTYPE 4 --#define MULTILINETYPE 5 --#define MULTIPOLYGONTYPE 6 --#define COLLECTIONTYPE 7 -+#define POINTTYPE 1 -+#define LINETYPE 2 -+#define POLYGONTYPE 3 -+#define MULTIPOINTTYPE 4 -+#define MULTILINETYPE 5 -+#define MULTIPOLYGONTYPE 6 -+#define COLLECTIONTYPE 7 - #define CIRCSTRINGTYPE 8 - #define COMPOUNDTYPE 9 - #define CURVEPOLYTYPE 10 -@@ -270,16 +280,16 @@ extern lwinterrupt_callback *lwgeom_regi - /******************************************************************/ - - typedef struct { -- double afac, bfac, cfac, dfac, efac, ffac, gfac, hfac, ifac, xoff, yoff, zoff; -+ double afac, bfac, cfac, dfac, efac, ffac, gfac, hfac, ifac, xoff, yoff, zoff; - } AFFINE; - - /******************************************************************/ - - typedef struct - { -- double xmin, ymin, zmin; -- double xmax, ymax, zmax; -- int32_t srid; -+ double xmin, ymin, zmin; -+ double xmax, ymax, zmax; -+ int32_t srid; - } - BOX3D; - -@@ -291,15 +301,15 @@ BOX3D; - */ - typedef struct - { -- uint8_t flags; -- double xmin; -- double xmax; -- double ymin; -- double ymax; -- double zmin; -- double zmax; -- double mmin; -- double mmax; -+ uint8_t flags; -+ double xmin; -+ double xmax; -+ double ymin; -+ double ymax; -+ double zmin; -+ double zmax; -+ double mmin; -+ double mmax; - } GBOX; - - -@@ -313,13 +323,13 @@ typedef struct - */ - typedef struct - { -- double a; /* semimajor axis */ -- double b; /* semiminor axis b = (a - fa) */ -- double f; /* flattening f = (a-b)/a */ -- double e; /* eccentricity (first) */ -- double e_sq; /* eccentricity squared (first) e_sq = (a*a-b*b)/(a*a) */ -- double radius; /* spherical average radius = (2*a+b)/3 */ -- char name[20]; /* name of ellipse */ -+ double a; /* semimajor axis */ -+ double b; /* semiminor axis b = (a - fa) */ -+ double f; /* flattening f = (a-b)/a */ -+ double e; /* eccentricity (first) */ -+ double e_sq; /* eccentricity squared (first) e_sq = (a*a-b*b)/(a*a) */ -+ double radius; /* spherical average radius = (2*a+b)/3 */ -+ char name[20]; /* name of ellipse */ - } - SPHEROID; - -@@ -328,31 +338,31 @@ SPHEROID; - */ - typedef struct - { -- double x, y; -+ double x, y; - } - POINT2D; - - typedef struct - { -- double x, y, z; -+ double x, y, z; - } - POINT3DZ; - - typedef struct - { -- double x, y, z; -+ double x, y, z; - } - POINT3D; - - typedef struct - { -- double x, y, m; -+ double x, y, m; - } - POINT3DM; - - typedef struct - { -- double x, y, z, m; -+ double x, y, z, m; - } - POINT4D; - -@@ -365,14 +375,14 @@ POINT4D; - */ - typedef struct - { -- /* Array of POINT 2D, 3D or 4D, possibly misaligned. */ -- uint8_t *serialized_pointlist; -+ /* Array of POINT 2D, 3D or 4D, possibly misaligned. */ -+ uint8_t *serialized_pointlist; - -- /* Use FLAGS_* macros to handle */ -- uint8_t flags; -+ /* Use FLAGS_* macros to handle */ -+ uint8_t flags; - -- uint32_t npoints; /* how many points we are currently storing */ -- uint32_t maxpoints; /* how many points we have space for in serialized_pointlist */ -+ uint32_t npoints; /* how many points we are currently storing */ -+ uint32_t maxpoints; /* how many points we have space for in serialized_pointlist */ - } - POINTARRAY; - -@@ -381,10 +391,10 @@ POINTARRAY; - */ - typedef struct - { -- uint32_t size; /* For PgSQL use only, use VAR* macros to manipulate. */ -- uint8_t srid[3]; /* 24 bits of SRID */ -- uint8_t flags; /* HasZ, HasM, HasBBox, IsGeodetic, IsReadOnly */ -- uint8_t data[1]; /* See gserialized.txt */ -+ uint32_t size; /* For PgSQL use only, use VAR* macros to manipulate. */ -+ uint8_t srid[3]; /* 24 bits of SRID */ -+ uint8_t flags; /* HasZ, HasM, HasBBox, IsGeodetic, IsReadOnly */ -+ uint8_t data[1]; /* See gserialized.txt */ - } GSERIALIZED; - - -@@ -396,198 +406,198 @@ typedef struct - */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- void *data; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ void *data; - } - LWGEOM; - - /* POINTYPE */ - typedef struct - { -- uint8_t type; /* POINTTYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- POINTARRAY *point; /* hide 2d/3d (this will be an array of 1 point) */ -+ uint8_t type; /* POINTTYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ POINTARRAY *point; /* hide 2d/3d (this will be an array of 1 point) */ - } - LWPOINT; /* "light-weight point" */ - - /* LINETYPE */ - typedef struct - { -- uint8_t type; /* LINETYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- POINTARRAY *points; /* array of POINT3D */ -+ uint8_t type; /* LINETYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ POINTARRAY *points; /* array of POINT3D */ - } - LWLINE; /* "light-weight line" */ - - /* TRIANGLE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- POINTARRAY *points; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ POINTARRAY *points; - } - LWTRIANGLE; - - /* CIRCSTRINGTYPE */ - typedef struct - { -- uint8_t type; /* CIRCSTRINGTYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- POINTARRAY *points; /* array of POINT(3D/3DM) */ -+ uint8_t type; /* CIRCSTRINGTYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ POINTARRAY *points; /* array of POINT(3D/3DM) */ - } - LWCIRCSTRING; /* "light-weight circularstring" */ - - /* POLYGONTYPE */ - typedef struct - { -- uint8_t type; /* POLYGONTYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t nrings; /* how many rings we are currently storing */ -- uint32_t maxrings; /* how many rings we have space for in **rings */ -- POINTARRAY **rings; /* list of rings (list of points) */ -+ uint8_t type; /* POLYGONTYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t nrings; /* how many rings we are currently storing */ -+ uint32_t maxrings; /* how many rings we have space for in **rings */ -+ POINTARRAY **rings; /* list of rings (list of points) */ - } - LWPOLY; /* "light-weight polygon" */ - - /* MULTIPOINTTYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWPOINT **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWPOINT **geoms; - } - LWMPOINT; - - /* MULTILINETYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWLINE **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWLINE **geoms; - } - LWMLINE; - - /* MULTIPOLYGONTYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWPOLY **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWPOLY **geoms; - } - LWMPOLY; - - /* COLLECTIONTYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWGEOM **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWGEOM **geoms; - } - LWCOLLECTION; - - /* COMPOUNDTYPE */ - typedef struct - { -- uint8_t type; /* COMPOUNDTYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWGEOM **geoms; -+ uint8_t type; /* COMPOUNDTYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWGEOM **geoms; - } - LWCOMPOUND; /* "light-weight compound line" */ - - /* CURVEPOLYTYPE */ - typedef struct - { -- uint8_t type; /* CURVEPOLYTYPE */ -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t nrings; /* how many rings we are currently storing */ -- uint32_t maxrings; /* how many rings we have space for in **rings */ -- LWGEOM **rings; /* list of rings (list of points) */ -+ uint8_t type; /* CURVEPOLYTYPE */ -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t nrings; /* how many rings we are currently storing */ -+ uint32_t maxrings; /* how many rings we have space for in **rings */ -+ LWGEOM **rings; /* list of rings (list of points) */ - } - LWCURVEPOLY; /* "light-weight polygon" */ - - /* MULTICURVE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWGEOM **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWGEOM **geoms; - } - LWMCURVE; - - /* MULTISURFACETYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWGEOM **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWGEOM **geoms; - } - LWMSURFACE; - - /* POLYHEDRALSURFACETYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWPOLY **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWPOLY **geoms; - } - LWPSURFACE; - - /* TINTYPE */ - typedef struct - { -- uint8_t type; -- uint8_t flags; -- GBOX *bbox; -- int32_t srid; -- uint32_t ngeoms; /* how many geometries we are currently storing */ -- uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -- LWTRIANGLE **geoms; -+ uint8_t type; -+ uint8_t flags; -+ GBOX *bbox; -+ int32_t srid; -+ uint32_t ngeoms; /* how many geometries we are currently storing */ -+ uint32_t maxgeoms; /* how many geometries we have space for in **geoms */ -+ LWTRIANGLE **geoms; - } - LWTIN; - -@@ -954,7 +964,7 @@ extern POINTARRAY *ptarray_addPoint(cons - - /** - * @brief Remove a point from a pointarray. -- * @param which - is the offset (starting at 0) -+ * @param which - is the offset (starting at 0) - * @return #POINTARRAY is newly allocated - */ - extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, uint32_t where); -@@ -1647,8 +1657,8 @@ extern double lwgeom_length_spheroid(con - extern int lwgeom_covers_lwgeom_sphere(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2); - - typedef struct { -- POINT2D* center; -- double radius; -+ POINT2D* center; -+ double radius; - } LWBOUNDINGCIRCLE; - - extern void lwboundingcircle_destroy(LWBOUNDINGCIRCLE* c); -@@ -2003,7 +2013,7 @@ extern int gserialized_get_gbox_p(const - #define LW_PARSER_CHECK_ZCLOSURE 8 - - #define LW_PARSER_CHECK_NONE 0 --#define LW_PARSER_CHECK_ALL (LW_PARSER_CHECK_MINPOINTS | LW_PARSER_CHECK_ODD | LW_PARSER_CHECK_CLOSURE) -+#define LW_PARSER_CHECK_ALL (LW_PARSER_CHECK_MINPOINTS | LW_PARSER_CHECK_ODD | LW_PARSER_CHECK_CLOSURE) - - /** - * Parser result structure: returns the result of attempting to convert -@@ -2011,14 +2021,14 @@ extern int gserialized_get_gbox_p(const - */ - typedef struct struct_lwgeom_parser_result - { -- const char *wkinput; /* Copy of pointer to input WKT/WKB */ -- uint8_t *serialized_lwgeom; /* Pointer to serialized LWGEOM */ -- size_t size; /* Size of serialized LWGEOM in bytes */ -- LWGEOM *geom; /* Pointer to LWGEOM struct */ -- const char *message; /* Error/warning message */ -- int errcode; /* Error/warning number */ -- int errlocation; /* Location of error */ -- int parser_check_flags; /* Bitmask of validity checks run during this parse */ -+ const char *wkinput; /* Copy of pointer to input WKT/WKB */ -+ uint8_t *serialized_lwgeom; /* Pointer to serialized LWGEOM */ -+ size_t size; /* Size of serialized LWGEOM in bytes */ -+ LWGEOM *geom; /* Pointer to LWGEOM struct */ -+ const char *message; /* Error/warning message */ -+ int errcode; /* Error/warning number */ -+ int errlocation; /* Location of error */ -+ int parser_check_flags; /* Bitmask of validity checks run during this parse */ - } - LWGEOM_PARSER_RESULT; - -@@ -2043,20 +2053,20 @@ LWGEOM_PARSER_RESULT; - */ - typedef struct struct_lwgeom_unparser_result - { -- uint8_t *serialized_lwgeom; /* Copy of pointer to input serialized LWGEOM */ -- char *wkoutput; /* Pointer to WKT or WKB output */ -- size_t size; /* Size of serialized LWGEOM in bytes */ -- const char *message; /* Error/warning message */ -- int errlocation; /* Location of error */ -+ uint8_t *serialized_lwgeom; /* Copy of pointer to input serialized LWGEOM */ -+ char *wkoutput; /* Pointer to WKT or WKB output */ -+ size_t size; /* Size of serialized LWGEOM in bytes */ -+ const char *message; /* Error/warning message */ -+ int errlocation; /* Location of error */ - } - LWGEOM_UNPARSER_RESULT; - - /* - * Unparser error messages (these must match the message array in lwgunparse.c) - */ --#define UNPARSER_ERROR_MOREPOINTS 1 --#define UNPARSER_ERROR_ODDPOINTS 2 --#define UNPARSER_ERROR_UNCLOSED 3 -+#define UNPARSER_ERROR_MOREPOINTS 1 -+#define UNPARSER_ERROR_ODDPOINTS 2 -+#define UNPARSER_ERROR_UNCLOSED 3 - - - /* -@@ -2200,27 +2210,27 @@ LWGEOM *lwgeom_unstroke(const LWGEOM *ge - * lwcurve_linearize - */ - typedef enum { -- /** -- * Tolerance expresses the number of segments to use -- * for each quarter of circle (quadrant). Must be -- * an integer. -- */ -- LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD = 0, -- /** -- * Tolerance expresses the maximum distance between -- * an arbitrary point on the curve and the closest -- * point to it on the resulting approximation, in -- * cartesian units. -- */ -- LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION = 1, -- /** -- * Tolerance expresses the maximum angle between -- * the radii generating approximation line vertices, -- * given in radiuses. A value of 1 would result -- * in an approximation of a semicircle composed by -- * 180 segments -- */ -- LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE = 2 -+ /** -+ * Tolerance expresses the number of segments to use -+ * for each quarter of circle (quadrant). Must be -+ * an integer. -+ */ -+ LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD = 0, -+ /** -+ * Tolerance expresses the maximum distance between -+ * an arbitrary point on the curve and the closest -+ * point to it on the resulting approximation, in -+ * cartesian units. -+ */ -+ LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION = 1, -+ /** -+ * Tolerance expresses the maximum angle between -+ * the radii generating approximation line vertices, -+ * given in radiuses. A value of 1 would result -+ * in an approximation of a semicircle composed by -+ * 180 segments -+ */ -+ LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE = 2 - } LW_LINEARIZE_TOLERANCE_TYPE; - - typedef enum { -@@ -2229,7 +2239,7 @@ typedef enum { - * vertices would be the same no matter the order - * of the points defining the input curve. - */ -- LW_LINEARIZE_FLAG_SYMMETRIC = 1 << 0, -+ LW_LINEARIZE_FLAG_SYMMETRIC = 1 << 0, - - /** - * Retain angle instructs the engine to try its best -@@ -2249,7 +2259,7 @@ typedef enum { - * instead be smaller (shorter) than the others. - * - */ -- LW_LINEARIZE_FLAG_RETAIN_ANGLE = 1 << 1 -+ LW_LINEARIZE_FLAG_RETAIN_ANGLE = 1 << 1 - } LW_LINEARIZE_FLAGS; - - /** -@@ -2332,6 +2342,9 @@ int lwgeom_is_simple(const LWGEOM *lwgeo - * PROJ4-dependent extra functions on LWGEOM - ******************************************************************************/ - -+int lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr); -+ -+#if POSTGIS_PROJ_VERSION < 60 - /** - * Get a projection from a string representation - * -@@ -2339,14 +2352,14 @@ int lwgeom_is_simple(const LWGEOM *lwgeo - */ - projPJ lwproj_from_string(const char* txt); - -+#endif - /** - * Transform (reproject) a geometry in-place. - * @param geom the geometry to transform -- * @param inpj the input (or current, or source) projection -- * @param outpj the output (or destination) projection -+ * @param PJ the input and output - */ --int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj); --int ptarray_transform(POINTARRAY *pa, projPJ inpj, projPJ outpj); -+int lwgeom_transform(LWGEOM *geom, PJ* pj); -+int ptarray_transform(POINTARRAY *pa, PJ* pj); - - - /******************************************************************************* -diff -rupN postgis-2.5.5/liblwgeom/liblwgeom_internal.h postgis-2.5.5-new/liblwgeom/liblwgeom_internal.h ---- postgis-2.5.5/liblwgeom/liblwgeom_internal.h 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/liblwgeom_internal.h 2022-08-06 11:48:23.733708197 +0200 -@@ -38,13 +38,14 @@ - #include - #include - #include -+#include -+#include -+#include - - #if HAVE_IEEEFP_H - #include - #endif - --#include -- - #include "liblwgeom.h" - - /** -@@ -363,11 +364,6 @@ char lwcollection_same(const LWCOLLECTIO - char lwcircstring_same(const LWCIRCSTRING *p1, const LWCIRCSTRING *p2); - - /* --* Transform --*/ --int point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj); -- --/* - * Shift - */ - void ptarray_longitude_shift(POINTARRAY *pa); -@@ -502,5 +498,6 @@ int ptarray_npoints_in_rect(const POINTA - int gbox_contains_point2d(const GBOX *g, const POINT2D *p); - int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt); - POINT4D* lwmpoint_extract_points_4d(const LWMPOINT* g, uint32_t* npoints, int* input_empty); -+char* lwstrdup(const char* a); - - #endif /* _LIBLWGEOM_INTERNAL_H */ -diff -rupN postgis-2.5.5/liblwgeom/lwgeom_transform.c postgis-2.5.5-new/liblwgeom/lwgeom_transform.c ---- postgis-2.5.5/liblwgeom/lwgeom_transform.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/lwgeom_transform.c 2022-08-06 11:59:22.562722935 +0200 -@@ -45,12 +45,53 @@ to_dec(POINT4D *pt) - pt->y *= 180.0/M_PI; - } - -+/***************************************************************************/ -+ -+#if POSTGIS_PROJ_VERSION < 60 -+ -+ -+static int -+point4d_transform(POINT4D *pt, PJ* pj) -+{ -+ POINT3D orig_pt = {pt->x, pt->y, pt->z}; /* Copy for error report*/ -+ -+ if (pj_is_latlong(pj->pj_from)) to_rad(pt) ; -+ -+ LWDEBUGF(4, "transforming POINT(%f %f) from '%s' to '%s'", -+ orig_pt.x, orig_pt.y, pj_get_def(pj->pj_from,0), pj_get_def(pj->pj_to,0)); -+ -+ if (pj_transform(pj->pj_from, pj->pj_to, 1, 0, &(pt->x), &(pt->y), &(pt->z)) != 0) -+ { -+ int pj_errno_val = *pj_get_errno_ref(); -+ if (pj_errno_val == -38) -+ { -+ lwnotice("PostGIS was unable to transform the point because either no grid" -+ " shift files were found, or the point does not lie within the " -+ "range for which the grid shift is defined. Refer to the " -+ "ST_Transform() section of the PostGIS manual for details on how " -+ "to configure PostGIS to alter this behaviour."); -+ lwerror("transform: couldn't project point (%g %g %g): %s (%d)", -+ orig_pt.x, orig_pt.y, orig_pt.z, -+ pj_strerrno(pj_errno_val), pj_errno_val); -+ } -+ else -+ { -+ lwerror("transform: %s (%d)", -+ pj_strerrno(pj_errno_val), pj_errno_val); -+ } -+ return LW_FAILURE; -+ } -+ -+ if (pj_is_latlong(pj->pj_to)) to_dec(pt); -+ return LW_SUCCESS; -+} -+ - /** - * Transform given POINTARRAY - * from inpj projection to outpj projection - */ - int --ptarray_transform(POINTARRAY *pa, projPJ inpj, projPJ outpj) -+ptarray_transform(POINTARRAY *pa, PJ* pj) - { - uint32_t i; - POINT4D p; -@@ -58,20 +99,51 @@ ptarray_transform(POINTARRAY *pa, projPJ - for ( i = 0; i < pa->npoints; i++ ) - { - getPoint4d_p(pa, i, &p); -- if ( ! point4d_transform(&p, inpj, outpj) ) return LW_FAILURE; -+ if ( ! point4d_transform(&p, pj) ) return LW_FAILURE; - ptarray_set_point4d(pa, i, &p); - } - - return LW_SUCCESS; - } - -+int -+lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr) -+{ -+ char *pj_errstr; -+ int rv; -+ PJ pj; -+ -+ pj.pj_from = lwproj_from_string(instr); -+ if (!pj.pj_from) -+ { -+ pj_errstr = pj_strerrno(*pj_get_errno_ref()); -+ if (!pj_errstr) pj_errstr = ""; -+ lwerror("could not parse proj string '%s'", instr); -+ return LW_FAILURE; -+ } -+ -+ pj.pj_to = lwproj_from_string(outstr); -+ if (!pj.pj_to) -+ { -+ pj_free(pj.pj_from); -+ pj_errstr = pj_strerrno(*pj_get_errno_ref()); -+ if (!pj_errstr) pj_errstr = ""; -+ lwerror("could not parse proj string '%s'", outstr); -+ return LW_FAILURE; -+ } -+ -+ rv = lwgeom_transform(geom, &pj); -+ pj_free(pj.pj_from); -+ pj_free(pj.pj_to); -+ return rv; -+} - - /** -- * Transform given SERIALIZED geometry -+ * Transform given LWGEOM geometry - * from inpj projection to outpj projection - */ - int --lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj) -+lwgeom_transform(LWGEOM *geom, PJ* pj) - { - uint32_t i; - -@@ -87,7 +159,7 @@ lwgeom_transform(LWGEOM *geom, projPJ in - case TRIANGLETYPE: - { - LWLINE *g = (LWLINE*)geom; -- if ( ! ptarray_transform(g->points, inpj, outpj) ) return LW_FAILURE; -+ if ( ! ptarray_transform(g->points, pj) ) return LW_FAILURE; - break; - } - case POLYGONTYPE: -@@ -95,7 +167,7 @@ lwgeom_transform(LWGEOM *geom, projPJ in - LWPOLY *g = (LWPOLY*)geom; - for ( i = 0; i < g->nrings; i++ ) - { -- if ( ! ptarray_transform(g->rings[i], inpj, outpj) ) return LW_FAILURE; -+ if ( ! ptarray_transform(g->rings[i], pj) ) return LW_FAILURE; - } - break; - } -@@ -113,7 +185,7 @@ lwgeom_transform(LWGEOM *geom, projPJ in - LWCOLLECTION *g = (LWCOLLECTION*)geom; - for ( i = 0; i < g->ngeoms; i++ ) - { -- if ( ! lwgeom_transform(g->geoms[i], inpj, outpj) ) return LW_FAILURE; -+ if ( ! lwgeom_transform(g->geoms[i], pj) ) return LW_FAILURE; - } - break; - } -@@ -127,52 +199,287 @@ lwgeom_transform(LWGEOM *geom, projPJ in - return LW_SUCCESS; - } - --int --point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj) -+projPJ -+lwproj_from_string(const char *str1) - { -- POINT3D orig_pt = {pt->x, pt->y, pt->z}; /* Copy for error report*/ -+ if (!str1 || str1[0] == '\0') -+ { -+ return NULL; -+ } -+ return pj_init_plus(str1); -+} - -- if (pj_is_latlong(srcpj)) to_rad(pt) ; -+/***************************************************************************/ - -- LWDEBUGF(4, "transforming POINT(%f %f) from '%s' to '%s'", -- orig_pt.x, orig_pt.y, pj_get_def(srcpj,0), pj_get_def(dstpj,0)); -+#else /* POSTGIS_PROJ_VERION >= 60 */ - -- if (pj_transform(srcpj, dstpj, 1, 0, &(pt->x), &(pt->y), &(pt->z)) != 0) -+int -+lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr) -+{ -+ PJ *pj = proj_create_crs_to_crs(NULL, instr, outstr, NULL); -+ if (!pj) - { -- int pj_errno_val = *pj_get_errno_ref(); -- if (pj_errno_val == -38) -+ PJ *pj_in = proj_create(NULL, instr); -+ PJ *pj_out = proj_create(NULL, outstr); -+ if (!pj_in) - { -- lwnotice("PostGIS was unable to transform the point because either no grid" -- " shift files were found, or the point does not lie within the " -- "range for which the grid shift is defined. Refer to the " -- "ST_Transform() section of the PostGIS manual for details on how " -- "to configure PostGIS to alter this behaviour."); -- lwerror("transform: couldn't project point (%g %g %g): %s (%d)", -- orig_pt.x, orig_pt.y, orig_pt.z, -- pj_strerrno(pj_errno_val), pj_errno_val); -+ lwerror("could not parse proj string '%s'", instr); - } -- else -+ if (!pj_out) - { -- lwerror("transform: couldn't project point (%g %g %g): %s (%d)", -- orig_pt.x, orig_pt.y, orig_pt.z, -- pj_strerrno(pj_errno_val), pj_errno_val); -+ proj_destroy(pj_in); -+ lwerror("could not parse proj string '%s'", outstr); - } - return LW_FAILURE; - } - -- if (pj_is_latlong(dstpj)) to_dec(pt); -+ return lwgeom_transform(geom, pj); -+} -+ -+int -+lwgeom_transform(LWGEOM* geom, PJ* pj) -+{ -+ uint32_t i; -+ -+ /* No points to transform in an empty! */ -+ if (lwgeom_is_empty(geom)) -+ return LW_SUCCESS; -+ -+ switch(geom->type) -+ { -+ case POINTTYPE: -+ case LINETYPE: -+ case CIRCSTRINGTYPE: -+ case TRIANGLETYPE: -+ { -+ LWLINE *g = (LWLINE*)geom; -+ if (!ptarray_transform(g->points, pj)) -+ return LW_FAILURE; -+ break; -+ } -+ case POLYGONTYPE: -+ { -+ LWPOLY *g = (LWPOLY*)geom; -+ for (i = 0; i < g->nrings; i++) -+ { -+ if (!ptarray_transform(g->rings[i], pj)) -+ return LW_FAILURE; -+ } -+ break; -+ } -+ case MULTIPOINTTYPE: -+ case MULTILINETYPE: -+ case MULTIPOLYGONTYPE: -+ case COLLECTIONTYPE: -+ case COMPOUNDTYPE: -+ case CURVEPOLYTYPE: -+ case MULTICURVETYPE: -+ case MULTISURFACETYPE: -+ case POLYHEDRALSURFACETYPE: -+ case TINTYPE: -+ { -+ LWCOLLECTION *g = (LWCOLLECTION*)geom; -+ for (i = 0; i < g->ngeoms; i++) -+ { -+ if (!lwgeom_transform(g->geoms[i], pj)) -+ return LW_FAILURE; -+ } -+ break; -+ } -+ default: -+ { -+ lwerror("lwgeom_transform: Cannot handle type '%s'", -+ lwtype_name(geom->type)); -+ return LW_FAILURE; -+ } -+ } - return LW_SUCCESS; - } - --projPJ --lwproj_from_string(const char *str1) -+static int -+proj_crs_is_swapped(const PJ* pj_crs) - { -- if (!str1 || str1[0] == '\0') -+ PJ *pj_cs; -+ int rv = LW_FALSE; -+ -+ if (proj_get_type(pj_crs) == PJ_TYPE_COMPOUND_CRS) - { -- return NULL; -+ PJ *pj_horiz_crs = proj_crs_get_sub_crs(NULL, pj_crs, 0); -+ pj_cs = proj_crs_get_coordinate_system(NULL, pj_horiz_crs); -+ proj_destroy(pj_horiz_crs); - } -- return pj_init_plus(str1); -+ else if (proj_get_type(pj_crs) == PJ_TYPE_BOUND_CRS) -+ { -+ PJ *pj_bound_crs = proj_get_source_crs(NULL, pj_crs); -+ pj_cs = proj_crs_get_coordinate_system(NULL, pj_bound_crs); -+ proj_destroy(pj_bound_crs); -+ } -+ else -+ { -+ pj_cs = proj_crs_get_coordinate_system(NULL, pj_crs); -+ } -+ int axis_count = proj_cs_get_axis_count(NULL, pj_cs); -+ if (axis_count > 0) -+ { -+ const char *out_name, *out_abbrev, *out_direction; -+ double out_unit_conv_factor; -+ const char *out_unit_name, *out_unit_auth_name, *out_unit_code; -+ /* Read only first axis, see if it is degrees / north */ -+ proj_cs_get_axis_info(NULL, pj_cs, 0, -+ &out_name, -+ &out_abbrev, -+ &out_direction, -+ &out_unit_conv_factor, -+ &out_unit_name, -+ &out_unit_auth_name, -+ &out_unit_code -+ ); -+ rv = (strcasecmp(out_direction, "north") == 0); -+ } -+ proj_destroy(pj_cs); -+ return rv; -+} -+ -+ -+int -+ptarray_transform(POINTARRAY* pa, PJ* pj) -+{ -+ uint32_t i; -+ POINT4D p; -+ size_t n_converted; -+ size_t n_points = pa->npoints; -+ size_t point_size = ptarray_point_size(pa); -+ int has_z = ptarray_has_z(pa); -+ double *pa_double = (double*)(pa->serialized_pointlist); -+ int input_swapped, output_swapped; -+ -+ /* XXXX TODO check that the PJ has decimal degrees as units in input/output */ -+ -+ PJ* pj_source_crs = proj_get_source_crs(NULL, pj); -+ PJ* pj_target_crs = proj_get_target_crs(NULL, pj); -+ -+ if (!(pj_source_crs && pj_source_crs)) -+ { -+ lwerror("ptarray_transform: unable to access source and target crs"); -+ return LW_FAILURE; -+ } -+ -+ input_swapped = proj_crs_is_swapped(pj_source_crs); -+ output_swapped = proj_crs_is_swapped(pj_target_crs); -+ proj_destroy(pj_source_crs); -+ proj_destroy(pj_target_crs); -+ -+ /* Convert to radians if necessary */ -+ if (proj_angular_input(pj, PJ_FWD)) -+ { -+ for (i = 0; i < pa->npoints; i++) -+ { -+ getPoint4d_p(pa, i, &p); -+ to_rad(&p); -+ } -+ } -+ -+ if (input_swapped) -+ ptarray_swap_ordinates(pa, LWORD_X, LWORD_Y); -+ -+ /* -+ * size_t proj_trans_generic(PJ *P, PJ_DIRECTION direction, -+ * double *x, size_t sx, size_t nx, -+ * double *y, size_t sy, size_t ny, -+ * double *z, size_t sz, size_t nz, -+ * double *t, size_t st, size_t nt) -+ */ -+ -+ n_converted = proj_trans_generic( -+ pj, PJ_FWD, -+ pa_double, point_size, n_points, /* X */ -+ pa_double + 1, point_size, n_points, /* Y */ -+ has_z ? pa_double + 2 : NULL, -+ has_z ? point_size : 0, -+ has_z ? n_points : 0, /* Z */ -+ NULL, 0, 0 /* M */ -+ ); -+ -+ if (n_converted != n_points) -+ { -+ lwerror("ptarray_transform: converted (%d) != input (%d)", -+ n_converted, n_points); -+ return LW_FAILURE; -+ } -+ -+ int pj_errno_val = proj_errno(pj); -+ if (pj_errno_val) -+ { -+ lwerror("transform: %s (%d)", -+ proj_errno_string(pj_errno_val), pj_errno_val); -+ return LW_FAILURE; -+ } -+ -+ if (output_swapped) -+ ptarray_swap_ordinates(pa, LWORD_X, LWORD_Y); -+ -+ /* Convert radians to degrees if necessary */ -+ if (proj_angular_output(pj, PJ_FWD)) -+ { -+ for (i = 0; i < pa->npoints; i++) -+ { -+ getPoint4d_p(pa, i, &p); -+ to_dec(&p); -+ } -+ } -+ -+ return LW_SUCCESS; - } - -+#if 0 -+int -+point4d_transform(POINT4D *pt, PJ* pj) -+{ -+ POINT4D pt_src = *pt; /* Copy for error report*/ -+ PJ_COORD pj_coord_src, pj_coord_dst; -+ int input_swapped = proj_crs_is_swapped(proj_get_source_crs(NULL, pj)); -+ int output_swapped = proj_crs_is_swapped(proj_get_target_crs(NULL, pj)); -+ -+ if (proj_angular_input(pj, PJ_FWD)) -+ to_rad(pt); -+ -+ LWDEBUGF(4, "transforming POINT(%f %f) using '%s'", -+ pt_src.x, pt_src.y, (proj_pj_info(pj)).definition); -+ -+ if (input_swapped) -+ pj_coord_src = proj_coord(pt->y, pt->x, pt->z, pt->m); -+ else -+ pj_coord_src = proj_coord(pt->x, pt->y, pt->z, pt->m); -+ -+ pj_coord_dst = proj_trans(pj, PJ_FWD, pj_coord_src); -+ -+ int pj_errno_val = proj_errno(pj); -+ if (pj_errno_val) -+ { -+ lwerror("point4d_transform: couldn't project point (%g %g %g): %s (%d)", -+ pt_src.x, pt_src.y, pt_src.z, -+ proj_errno_string(pj_errno_val), pj_errno_val); -+ return LW_FAILURE; -+ } -+ -+ if (output_swapped) -+ { -+ pt->x = pj_coord_dst.xyzt.x; -+ pt->y = pj_coord_dst.xyzt.y; -+ } -+ else -+ { -+ pt->x = pj_coord_dst.xyzt.x; -+ pt->y = pj_coord_dst.xyzt.y; -+ } -+ pt->z = pj_coord_dst.xyzt.z; -+ pt->m = pt_src.m; -+ -+ if (proj_angular_output(pj, PJ_FWD)) -+ to_dec(pt); -+ return LW_SUCCESS; -+} -+#endif /* point4d_transform */ - - -+#endif -diff -rupN postgis-2.5.5/liblwgeom/lwin_encoded_polyline.c postgis-2.5.5-new/liblwgeom/lwin_encoded_polyline.c ---- postgis-2.5.5/liblwgeom/lwin_encoded_polyline.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/lwin_encoded_polyline.c 2022-08-06 11:48:23.734708197 +0200 -@@ -25,6 +25,8 @@ - - #include - #include -+#include -+ - #include "liblwgeom.h" - #include "../postgis_config.h" - -diff -rupN postgis-2.5.5/liblwgeom/lwspheroid.c postgis-2.5.5-new/liblwgeom/lwspheroid.c ---- postgis-2.5.5/liblwgeom/lwspheroid.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/lwspheroid.c 2022-08-06 11:48:23.735708197 +0200 -@@ -28,8 +28,8 @@ - #include "lwgeodetic.h" - #include "lwgeom_log.h" - --/* GeographicLib */ --#if PROJ_GEODESIC -+/* In proj4.9, GeographicLib is in special header */ -+#ifdef PROJ_GEODESIC - #include - #endif - -@@ -45,7 +45,7 @@ void spheroid_init(SPHEROID *s, double a - s->radius = (2.0 * a + b ) / 3.0; - } - --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - static double spheroid_mu2(double alpha, const SPHEROID *s) - { - double b2 = POW2(s->b); -@@ -64,7 +64,7 @@ static double spheroid_big_b(double u2) - #endif /* ! PROJ_GEODESIC */ - - --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - - /** - * Computes the shortest distance along the surface of the spheroid -@@ -165,7 +165,7 @@ static double ptarray_area_spheroid(cons - return fabs(area); - } - --/* Above use GeographicLib */ -+/* Above use Proj GeographicLib */ - #else /* ! PROJ_GEODESIC */ - /* Below use pre-version 2.2 geodesic functions */ - -diff -rupN postgis-2.5.5/liblwgeom/lwunionfind.c postgis-2.5.5-new/liblwgeom/lwunionfind.c ---- postgis-2.5.5/liblwgeom/lwunionfind.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/lwunionfind.c 2022-08-06 11:48:23.735708197 +0200 -@@ -26,6 +26,7 @@ - #include "liblwgeom.h" - #include "lwunionfind.h" - #include -+#include - - static int cmp_int(const void *a, const void *b); - static int cmp_int_ptr(const void *a, const void *b); -diff -rupN postgis-2.5.5/liblwgeom/lwutil.c postgis-2.5.5-new/liblwgeom/lwutil.c ---- postgis-2.5.5/liblwgeom/lwutil.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/lwutil.c 2022-08-06 11:48:23.735708197 +0200 -@@ -246,6 +246,15 @@ lwfree(void *mem) - lwfree_var(mem); - } - -+char * -+lwstrdup(const char* a) -+{ -+ size_t l = strlen(a)+1; -+ char *b = lwalloc(l); -+ strncpy(b, a, l); -+ return b; -+} -+ - /* - * Returns a new string which contains a maximum of maxlength characters starting - * from startpos and finishing at endpos (0-based indexing). If the string is -diff -rupN postgis-2.5.5/liblwgeom/ptarray.c postgis-2.5.5-new/liblwgeom/ptarray.c ---- postgis-2.5.5/liblwgeom/ptarray.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/liblwgeom/ptarray.c 2022-08-06 11:48:23.736708197 +0200 -@@ -26,6 +26,7 @@ - - #include - #include -+#include - - #include "../postgis_config.h" - /*#define POSTGIS_DEBUG_LEVEL 4*/ -@@ -390,8 +391,8 @@ ptarray_swap_ordinates(POINTARRAY *pa, L - double d, *dp1, *dp2; - POINT4D p; - -- dp1 = ((double*)&p)+(unsigned)o1; -- dp2 = ((double*)&p)+(unsigned)o2; -+ dp1 = ((double*)&p)+(unsigned)o1; -+ dp2 = ((double*)&p)+(unsigned)o2; - for (i=0 ; i < pa->npoints ; i++) - { - getPoint4d_p(pa, i, &p); -diff -rupN postgis-2.5.5/libpgcommon/lwgeom_cache.c postgis-2.5.5-new/libpgcommon/lwgeom_cache.c ---- postgis-2.5.5/libpgcommon/lwgeom_cache.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/libpgcommon/lwgeom_cache.c 2022-08-06 11:48:23.737708197 +0200 -@@ -77,35 +77,36 @@ GetGenericCacheCollection(FunctionCallIn - - - /** --* Get the Proj4 entry from the generic cache if one exists. -+* Get the Proj entry from the generic cache if one exists. - * If it doesn't exist, make a new empty one and return it. - */ --PROJ4PortalCache * --GetPROJ4SRSCache(FunctionCallInfo fcinfo) -+PROJPortalCache * -+GetPROJSRSCache(FunctionCallInfo fcinfo) - { - GenericCacheCollection* generic_cache = GetGenericCacheCollection(fcinfo); -- PROJ4PortalCache* cache = (PROJ4PortalCache*)(generic_cache->entry[PROJ_CACHE_ENTRY]); -+ PROJPortalCache* cache = (PROJPortalCache*)(generic_cache->entry[PROJ_CACHE_ENTRY]); - - if ( ! cache ) - { - /* Allocate in the upper context */ -- cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(PROJ4PortalCache)); -+ cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(PROJPortalCache)); - - if (cache) - { - int i; - -- POSTGIS_DEBUGF(3, "Allocating PROJ4Cache for portal with transform() MemoryContext %p", FIContext(fcinfo)); -+ POSTGIS_DEBUGF(3, "Allocating PROJCache for portal with transform() MemoryContext %p", FIContext(fcinfo)); - /* Put in any required defaults */ -- for (i = 0; i < PROJ4_CACHE_ITEMS; i++) -+ for (i = 0; i < PROJ_CACHE_ITEMS; i++) - { -- cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN; -- cache->PROJ4SRSCache[i].projection = NULL; -- cache->PROJ4SRSCache[i].projection_mcxt = NULL; -+ cache->PROJSRSCache[i].srid_from = SRID_UNKNOWN; -+ cache->PROJSRSCache[i].srid_to = SRID_UNKNOWN; -+ cache->PROJSRSCache[i].projection = NULL; -+ cache->PROJSRSCache[i].projection_mcxt = NULL; - } - cache->type = PROJ_CACHE_ENTRY; -- cache->PROJ4SRSCacheCount = 0; -- cache->PROJ4SRSCacheContext = FIContext(fcinfo); -+ cache->PROJSRSCacheCount = 0; -+ cache->PROJSRSCacheContext = FIContext(fcinfo); - - /* Store the pointer in GenericCache */ - generic_cache->entry[PROJ_CACHE_ENTRY] = (GenericCache*)cache; -diff -rupN postgis-2.5.5/libpgcommon/lwgeom_cache.h postgis-2.5.5-new/libpgcommon/lwgeom_cache.h ---- postgis-2.5.5/libpgcommon/lwgeom_cache.h 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/libpgcommon/lwgeom_cache.h 2022-08-06 11:48:23.737708197 +0200 -@@ -62,31 +62,32 @@ typedef struct { - * fcinfo->flinfo->fn_extra to avoid collisions. - */ - --/* An entry in the PROJ4 SRS cache */ --typedef struct struct_PROJ4SRSCacheItem -+/* An entry in the PROJ SRS cache */ -+typedef struct struct_PROJSRSCacheItem - { -- int srid; -- projPJ projection; -+ int srid_from; -+ int srid_to; -+ PJ* projection; - MemoryContext projection_mcxt; - } --PROJ4SRSCacheItem; -+PROJSRSCacheItem; - - /* PROJ 4 lookup transaction cache methods */ --#define PROJ4_CACHE_ITEMS 8 -+#define PROJ_CACHE_ITEMS 8 - - /* - * The proj4 cache holds a fixed number of reprojection - * entries. In normal usage we don't expect it to have - * many entries, so we always linearly scan the list. - */ --typedef struct struct_PROJ4PortalCache -+typedef struct struct_PROJPortalCache - { - int type; -- PROJ4SRSCacheItem PROJ4SRSCache[PROJ4_CACHE_ITEMS]; -- int PROJ4SRSCacheCount; -- MemoryContext PROJ4SRSCacheContext; -+ PROJSRSCacheItem PROJSRSCache[PROJ_CACHE_ITEMS]; -+ int PROJSRSCacheCount; -+ MemoryContext PROJSRSCacheContext; - } --PROJ4PortalCache; -+PROJPortalCache; - - /** - * Generic signature for functions to manage a geometry -@@ -103,7 +104,7 @@ typedef struct - /* - * Cache retrieval functions - */ --PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfo fcinfo); -+PROJPortalCache *GetPROJSRSCache(FunctionCallInfo fcinfo); - GeomCache *GetGeomCache(FunctionCallInfo fcinfo, - const GeomCacheMethods *cache_methods, - const GSERIALIZED *g1, -diff -rupN postgis-2.5.5/libpgcommon/lwgeom_transform.c postgis-2.5.5-new/libpgcommon/lwgeom_transform.c ---- postgis-2.5.5/libpgcommon/lwgeom_transform.c 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/libpgcommon/lwgeom_transform.c 2022-08-06 12:22:51.237754447 +0200 -@@ -34,37 +34,51 @@ - #include - - -+/** -+* Global variable to hold cached information about what -+* schema functions are installed in. Currently used by -+* SetSpatialRefSysSchema and GetProjStringsSPI -+*/ -+static char *spatialRefSysSchema = NULL; - - --/* Expose an internal Proj function */ --int pj_transform_nodatum(projPJ srcdefn, projPJ dstdefn, long point_count, int point_offset, double *x, double *y, double *z ); -- - /* - * PROJ 4 backend hash table initial hash size - * (since 16 is the default portal hash table size, and we would - * typically have 2 entries per portal - * then we shall use a default size of 32) - */ --#define PROJ4_BACKEND_HASH_SIZE 32 -+#define PROJ_BACKEND_HASH_SIZE 32 - - - /** -- * Backend projPJ hash table -+ * Backend PROJ hash table - * -- * This hash table stores a key/value pair of MemoryContext/projPJ objects. -- * Whenever we create a projPJ object using pj_init(), we create a separate -+ * This hash table stores a key/value pair of MemoryContext/PJ objects. -+ * Whenever we create a PJ object using pj_init(), we create a separate - * MemoryContext as a child context of the current executor context. -- * The MemoryContext/projPJ object is stored in this hash table so -- * that when PROJ4SRSCacheDelete() is called during query cleanup, we can -- * lookup the projPJ object based upon the MemoryContext parameter and hence -+ * The MemoryContext/PJ object is stored in this hash table so -+ * that when PROJSRSCacheDelete() is called during query cleanup, we can -+ * lookup the PJ object based upon the MemoryContext parameter and hence - * pj_free() it. - */ - static HTAB *PJHash = NULL; - -+/** -+ * Utility structure to get many potential string representations -+ * from spatial_ref_sys query. -+ */ -+typedef struct { -+ char* epsgtext; -+ char* srtext; -+ char* proj4text; -+} PjStrs; -+ -+ - typedef struct struct_PJHashEntry - { - MemoryContext ProjectionContext; -- projPJ projection; -+ PJ* projection; - } - PJHashEntry; - -@@ -73,42 +87,92 @@ PJHashEntry; - uint32 mcxt_ptr_hash(const void *key, Size keysize); - - static HTAB *CreatePJHash(void); --static void AddPJHashEntry(MemoryContext mcxt, projPJ projection); --static projPJ GetPJHashEntry(MemoryContext mcxt); - static void DeletePJHashEntry(MemoryContext mcxt); -+static PJ* GetPJHashEntry(MemoryContext mcxt); -+static void AddPJHashEntry(MemoryContext mcxt, PJ* projection); - - /* Internal Cache API */ --/* static PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfo fcinfo) ; */ --static bool IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid); --static projPJ GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid); --static void AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid); --static void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid); -+/* static PROJPortalCache *GetPROJSRSCache(FunctionCallInfo fcinfo) ; */ -+static bool IsInPROJSRSCache(PROJPortalCache *PROJCache, int srid_from, int srid_to); -+static void AddToPROJSRSCache(PROJPortalCache *PROJCache, int srid_from, int srid_to); -+static void DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, int srid_from, int srid_to); -+ - - /* Search path for PROJ.4 library */ --static bool IsPROJ4LibPathSet = false; --void SetPROJ4LibPath(void); -+static bool IsPROJLibPathSet = false; -+void SetPROJLibPath(void); -+ -+ -+/* -+* Given a function call context, figure out what namespace the -+* function is being called from, and copy that into a global -+* for use by GetProjStringsSPI -+*/ -+static void -+SetSpatialRefSysSchema(FunctionCallInfo fcinfo) -+{ -+ char *nsp_name; -+ -+ /* Schema info is already cached, we're done here */ -+ if (spatialRefSysSchema) return; -+ -+ /* For some reason we have a hobbled fcinfo/flinfo */ -+ if (!fcinfo || !fcinfo->flinfo) return; -+ -+ nsp_name = get_namespace_name(get_func_namespace(fcinfo->flinfo->fn_oid)); -+ /* early exit if we cannot lookup nsp_name, cf #4067 */ -+ if (!nsp_name) return; -+ -+ elog(DEBUG4, "%s located %s in namespace %s", __func__, get_func_name(fcinfo->flinfo->fn_oid), nsp_name); -+ spatialRefSysSchema = MemoryContextStrdup(CacheMemoryContext, nsp_name); -+ return; -+} -+ -+static void -+PROJSRSDestroyPJ(PJ* pj) -+{ -+#if POSTGIS_PROJ_VERSION < 60 -+/* Ape the Proj 6+ API for versions < 6 */ -+ if (pj->pj_from) -+ pj_free(pj->pj_from); -+ if (pj->pj_to) -+ pj_free(pj->pj_to); -+ free(pj); -+#else -+ proj_destroy(pj); -+#endif -+} - -+#if 0 -+static const char * -+PJErrStr() -+{ -+ const char *pj_errstr = pj_strerrno(*pj_get_errno_ref()); -+ if (!pj_errstr) -+ return ""; -+ return pj_errstr; -+} -+#endif - - static void - #if POSTGIS_PGSQL_VERSION < 96 --PROJ4SRSCacheDelete(MemoryContext context) -+PROJSRSCacheDelete(MemoryContext context) - { - #else --PROJ4SRSCacheDelete(void *ptr) -+PROJSRSCacheDelete(void *ptr) - { - MemoryContext context = (MemoryContext)ptr; - #endif -- projPJ projection; - -- /* Lookup the projPJ pointer in the global hash table so we can free it */ -- projection = GetPJHashEntry(context); -+ /* Lookup the PJ pointer in the global hash table so we can free it */ -+ PJ* projection = GetPJHashEntry(context); - - if (!projection) -- elog(ERROR, "PROJ4SRSCacheDelete: Trying to delete non-existant projection object with MemoryContext key (%p)", (void *)context); -+ elog(ERROR, "PROJSRSCacheDelete: Trying to delete non-existant projection object with MemoryContext key (%p)", (void *)context); - - POSTGIS_DEBUGF(3, "deleting projection object (%p) with MemoryContext key (%p)", projection, context); - /* Free it */ -- pj_free(projection); -+ PROJSRSDestroyPJ(projection); - - /* Remove the hash entry as it is no longer needed */ - DeletePJHashEntry(context); -@@ -117,7 +181,7 @@ PROJ4SRSCacheDelete(void *ptr) - #if POSTGIS_PGSQL_VERSION < 96 - - static void --PROJ4SRSCacheInit(MemoryContext context) -+PROJSRSCacheInit(MemoryContext context) - { - /* - * Do nothing as the cache is initialised when the transform() -@@ -126,7 +190,7 @@ PROJ4SRSCacheInit(MemoryContext context) - } - - static void --PROJ4SRSCacheReset(MemoryContext context) -+PROJSRSCacheReset(MemoryContext context) - { - /* - * Do nothing, but we must supply a function since this call is mandatory according to tgl -@@ -135,7 +199,7 @@ PROJ4SRSCacheReset(MemoryContext context - } - - static bool --PROJ4SRSCacheIsEmpty(MemoryContext context) -+PROJSRSCacheIsEmpty(MemoryContext context) - { - /* - * Always return false since this call is mandatory according to tgl -@@ -145,19 +209,19 @@ PROJ4SRSCacheIsEmpty(MemoryContext conte - } - - static void --PROJ4SRSCacheStats(MemoryContext context, int level) -+PROJSRSCacheStats(MemoryContext context, int level) - { - /* - * Simple stats display function - we must supply a function since this call is mandatory according to tgl - * (see postgis-devel archives July 2007) - */ - -- fprintf(stderr, "%s: PROJ4 context\n", context->name); -+ fprintf(stderr, "%s: PROJ context\n", context->name); - } - - #ifdef MEMORY_CONTEXT_CHECKING - static void --PROJ4SRSCacheCheck(MemoryContext context) -+PROJSRSCacheCheck(MemoryContext context) - { - /* - * Do nothing - stub required for when PostgreSQL is compiled -@@ -167,26 +231,26 @@ PROJ4SRSCacheCheck(MemoryContext context - #endif - - /* Memory context definition must match the current version of PostgreSQL */ --static MemoryContextMethods PROJ4SRSCacheContextMethods = -+static MemoryContextMethods PROJSRSCacheContextMethods = - { - NULL, - NULL, - NULL, -- PROJ4SRSCacheInit, -- PROJ4SRSCacheReset, -- PROJ4SRSCacheDelete, -+ PROJSRSCacheInit, -+ PROJSRSCacheReset, -+ PROJSRSCacheDelete, - NULL, -- PROJ4SRSCacheIsEmpty, -- PROJ4SRSCacheStats -+ PROJSRSCacheIsEmpty, -+ PROJSRSCacheStats - #ifdef MEMORY_CONTEXT_CHECKING -- ,PROJ4SRSCacheCheck -+ ,PROJSRSCacheCheck - #endif - }; - - #endif /* POSTGIS_PGSQL_VERSION < 96 */ - - /* -- * PROJ4 projPJ Hash Table functions -+ * PROJ PJ Hash Table functions - */ - - -@@ -213,10 +277,10 @@ static HTAB *CreatePJHash(void) - ctl.entrysize = sizeof(PJHashEntry); - ctl.hash = mcxt_ptr_hash; - -- return hash_create("PostGIS PROJ4 Backend projPJ MemoryContext Hash", PROJ4_BACKEND_HASH_SIZE, &ctl, (HASH_ELEM | HASH_FUNCTION)); -+ return hash_create("PostGIS PROJ Backend MemoryContext Hash", PROJ_BACKEND_HASH_SIZE, &ctl, (HASH_ELEM | HASH_FUNCTION)); - } - --static void AddPJHashEntry(MemoryContext mcxt, projPJ projection) -+static void AddPJHashEntry(MemoryContext mcxt, PJ* projection) - { - bool found; - void **key; -@@ -225,7 +289,7 @@ static void AddPJHashEntry(MemoryContext - /* The hash key is the MemoryContext pointer */ - key = (void *)&mcxt; - -- he = (PJHashEntry *) hash_search(PJHash, key, HASH_ENTER, &found); -+ he = (PJHashEntry*) hash_search(PJHash, key, HASH_ENTER, &found); - if (!found) - { - /* Insert the entry into the new hash element */ -@@ -234,12 +298,12 @@ static void AddPJHashEntry(MemoryContext - } - else - { -- elog(ERROR, "AddPJHashEntry: PROJ4 projection object already exists for this MemoryContext (%p)", -+ elog(ERROR, "AddPJHashEntry: PROJ projection object already exists for this MemoryContext (%p)", - (void *)mcxt); - } - } - --static projPJ GetPJHashEntry(MemoryContext mcxt) -+static PJ* GetPJHashEntry(MemoryContext mcxt) - { - void **key; - PJHashEntry *he; -@@ -266,118 +330,140 @@ static void DeletePJHashEntry(MemoryCont - he = (PJHashEntry *) hash_search(PJHash, key, HASH_REMOVE, NULL); - - if (!he) -- elog(ERROR, "DeletePJHashEntry: There was an error removing the PROJ4 projection object from this MemoryContext (%p)", (void *)mcxt); -+ elog(ERROR, "DeletePJHashEntry: There was an error removing the PROJ projection object from this MemoryContext (%p)", (void *)mcxt); - else - he->projection = NULL; - } - --bool --IsInPROJ4Cache(Proj4Cache PROJ4Cache, int srid) { -- return IsInPROJ4SRSCache((PROJ4PortalCache *)PROJ4Cache, srid) ; --} -- --/* -+/***************************************************************************** - * Per-cache management functions - */ - - static bool --IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid) -+IsInPROJSRSCache(PROJPortalCache *cache, int srid_from, int srid_to) - { - /* - * Return true/false depending upon whether the item - * is in the SRS cache. - */ -- -- int i; -- -- for (i = 0; i < PROJ4_CACHE_ITEMS; i++) -+ uint32_t i; -+ for (i = 0; i < PROJ_CACHE_ITEMS; i++) - { -- if (PROJ4Cache->PROJ4SRSCache[i].srid == srid) -- return 1; -+ if (cache->PROJSRSCache[i].srid_from == srid_from && -+ cache->PROJSRSCache[i].srid_to == srid_to) -+ return true; - } -- - /* Otherwise not found */ -- return 0; -+ return false; - } - --projPJ GetProjectionFromPROJ4Cache(Proj4Cache cache, int srid) -+static PJ* -+GetProjectionFromPROJCache(PROJPortalCache *cache, int srid_from, int srid_to) - { -- return GetProjectionFromPROJ4SRSCache((PROJ4PortalCache *)cache, srid) ; -+ uint32_t i; -+ for (i = 0; i < PROJ_CACHE_ITEMS; i++) -+ { -+ if (cache->PROJSRSCache[i].srid_from == srid_from && -+ cache->PROJSRSCache[i].srid_to == srid_to) -+ return cache->PROJSRSCache[i].projection; -+ } -+ -+ return NULL; - } - --/** -- * Return the projection object from the cache (we should -- * already have checked it exists using IsInPROJ4SRSCache first) -- */ --static projPJ --GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid) -+static char* -+SPI_pstrdup(const char* str) - { -- int i; -- -- for (i = 0; i < PROJ4_CACHE_ITEMS; i++) -+ char* ostr = NULL; -+ if (str) - { -- if (PROJ4Cache->PROJ4SRSCache[i].srid == srid) -- return PROJ4Cache->PROJ4SRSCache[i].projection; -+ ostr = SPI_palloc(strlen(str)+1); -+ strcpy(ostr, str); - } -- -- return NULL; -+ return ostr; - } - --char* GetProj4StringSPI(int srid) -+static PjStrs -+GetProjStringsSPI(int srid) - { -- static int maxproj4len = 512; -+ const int maxprojlen = 512; -+ const int spibufferlen = 512; - int spi_result; -- char *proj_str = palloc(maxproj4len); -- char proj4_spi_buffer[256]; -+ char proj_spi_buffer[spibufferlen]; -+ PjStrs strs; -+ memset(&strs, 0, sizeof(strs)); - - /* Connect */ - spi_result = SPI_connect(); - if (spi_result != SPI_OK_CONNECT) - { -- elog(ERROR, "GetProj4StringSPI: Could not connect to database using SPI"); -+ elog(ERROR, "Could not connect to database using SPI"); - } - -- static char *proj_str_tmpl = -- "SELECT proj4text, auth_name, auth_srid, srtext " -- "FROM %s " -- "WHERE srid = %d " -- "LIMIT 1"; -- snprintf(proj4_spi_buffer, 255, proj_str_tmpl, postgis_spatial_ref_sys(), srid); -+ /* -+ * This global is allocated in CacheMemoryContext (lifespan of this backend) -+ * and is set by SetSpatialRefSysSchema the first time -+ * that GetPJUsingFCInfo is called. -+ */ -+ static char *proj_str_tmpl = "SELECT proj4text, auth_name, auth_srid, srtext " -+ "FROM %s%sspatial_ref_sys " -+ "WHERE srid = %d " -+ "LIMIT 1"; -+ if (spatialRefSysSchema) -+ { -+ snprintf(proj_spi_buffer, spibufferlen, proj_str_tmpl, spatialRefSysSchema, ".", srid); -+ } -+ else -+ { -+ snprintf(proj_spi_buffer, spibufferlen, proj_str_tmpl, "", "", srid); -+ } - - /* Execute the query, noting the readonly status of this SQL */ -- spi_result = SPI_execute(proj4_spi_buffer, true, 1); -+ spi_result = SPI_execute(proj_spi_buffer, true, 1); - -- /* Read back the PROJ4 text */ -+ /* Read back the PROJ text */ - if (spi_result == SPI_OK_SELECT && SPI_processed > 0) - { - /* Select the first (and only tuple) */ - TupleDesc tupdesc = SPI_tuptable->tupdesc; - SPITupleTable *tuptable = SPI_tuptable; - HeapTuple tuple = tuptable->vals[0]; -- char *proj4text = SPI_getvalue(tuple, tupdesc, 1); -- -- if ( proj4text ) -- { -- /* Make a projection object out of it */ -- strncpy(proj_str, proj4text, maxproj4len - 1); -- } -- else -- { -- proj_str[0] = 0; -- } -+ /* Always return the proj4text */ -+ char* proj4text = SPI_getvalue(tuple, tupdesc, 1); -+ if (proj4text && strlen(proj4text)) -+ strs.proj4text = SPI_pstrdup(proj4text); -+ -+ /* For Proj >= 6 prefer "EPSG:XXXX" to proj strings */ -+ /* as proj_create_crs_to_crs() will give us more consistent */ -+ /* results with EPSG numbers than with proj strings */ -+ char* authname = SPI_getvalue(tuple, tupdesc, 2); -+ char* authsrid = SPI_getvalue(tuple, tupdesc, 3); -+ if (authname && authsrid && -+ strcmp(authname,"EPSG") == 0 && -+ strlen(authsrid)) -+ { -+ char tmp[maxprojlen]; -+ snprintf(tmp, maxprojlen, "EPSG:%s", authsrid); -+ strs.epsgtext = SPI_pstrdup(tmp); -+ } -+ -+ /* Proj6+ can parse srtext, so return that too */ -+ char* srtext = SPI_getvalue(tuple, tupdesc, 4); -+ if (srtext && strlen(srtext)) -+ strs.srtext = SPI_pstrdup(srtext); - } - else - { -- elog(ERROR, "GetProj4StringSPI: Cannot find SRID (%d) in spatial_ref_sys", srid); -+ elog(ERROR, "Cannot find SRID (%d) in spatial_ref_sys", srid); - } - - spi_result = SPI_finish(); - if (spi_result != SPI_OK_FINISH) - { -- elog(ERROR, "GetProj4StringSPI: Could not disconnect from database using SPI"); -+ elog(ERROR, "Could not disconnect from database using SPI"); - } - -- return proj_str; -+ return strs; - } - - -@@ -387,29 +473,32 @@ char* GetProj4StringSPI(int srid) - * (WGS84 UTM N/S, Polar Stereographic N/S - see SRID_* macros), - * return the proj4text for those. - */ --static char* GetProj4String(int srid) -+static PjStrs -+GetProjStrings(int srid) - { -- static int maxproj4len = 512; -+ const int maxprojlen = 512; -+ PjStrs strs; -+ memset(&strs, 0, sizeof(strs)); - - /* SRIDs in SPATIAL_REF_SYS */ - if ( srid < SRID_RESERVE_OFFSET ) - { -- return GetProj4StringSPI(srid); -+ return GetProjStringsSPI(srid); - } - /* Automagic SRIDs */ - else - { -- char *proj_str = palloc(maxproj4len); -+ strs.proj4text = palloc(maxprojlen); - int id = srid; - /* UTM North */ - if ( id >= SRID_NORTH_UTM_START && id <= SRID_NORTH_UTM_END ) - { -- snprintf(proj_str, maxproj4len, "+proj=utm +zone=%d +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - SRID_NORTH_UTM_START + 1); -+ snprintf(strs.proj4text, maxprojlen, "+proj=utm +zone=%d +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - SRID_NORTH_UTM_START + 1); - } - /* UTM South */ - else if ( id >= SRID_SOUTH_UTM_START && id <= SRID_SOUTH_UTM_END ) - { -- snprintf(proj_str, maxproj4len, "+proj=utm +zone=%d +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - SRID_SOUTH_UTM_START + 1); -+ snprintf(strs.proj4text, maxprojlen, "+proj=utm +zone=%d +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - SRID_SOUTH_UTM_START + 1); - } - /* Lambert zones (about 30x30, larger in higher latitudes) */ - /* There are three latitude zones, divided at -90,-60,-30,0,30,60,90. */ -@@ -434,102 +523,190 @@ static char* GetProj4String(int srid) - else - lwerror("Unknown yzone encountered!"); - -- snprintf(proj_str, maxproj4len, "+proj=laea +ellps=WGS84 +datum=WGS84 +lat_0=%g +lon_0=%g +units=m +no_defs", lat_0, lon_0); -+ snprintf(strs.proj4text, maxprojlen, "+proj=laea +ellps=WGS84 +datum=WGS84 +lat_0=%g +lon_0=%g +units=m +no_defs", lat_0, lon_0); - } - /* Lambert Azimuthal Equal Area South Pole */ - else if ( id == SRID_SOUTH_LAMBERT ) - { -- strncpy(proj_str, "+proj=laea +lat_0=-90 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len ); -+ strncpy(strs.proj4text, "+proj=laea +lat_0=-90 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxprojlen ); - } - /* Polar Sterographic South */ - else if ( id == SRID_SOUTH_STEREO ) - { -- strncpy(proj_str, "+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len); -+ strncpy(strs.proj4text, "+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxprojlen); - } - /* Lambert Azimuthal Equal Area North Pole */ - else if ( id == SRID_NORTH_LAMBERT ) - { -- strncpy(proj_str, "+proj=laea +lat_0=90 +lon_0=-40 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len ); -+ strncpy(strs.proj4text, "+proj=laea +lat_0=90 +lon_0=-40 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxprojlen ); - } - /* Polar Stereographic North */ - else if ( id == SRID_NORTH_STEREO ) - { -- strncpy(proj_str, "+proj=stere +lat_0=90 +lat_ts=71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len ); -+ strncpy(strs.proj4text, "+proj=stere +lat_0=90 +lat_ts=71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxprojlen ); - } - /* World Mercator */ - else if ( id == SRID_WORLD_MERCATOR ) - { -- strncpy(proj_str, "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len ); -+ strncpy(strs.proj4text, "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxprojlen ); - } - else - { - elog(ERROR, "Invalid reserved SRID (%d)", srid); -- return NULL; -+ return strs; - } - -- POSTGIS_DEBUGF(3, "returning on SRID=%d: %s", srid, proj_str); -- return proj_str; -+ POSTGIS_DEBUGF(3, "returning on SRID=%d: %s", srid, strs.proj4text); -+ return strs; - } - } - --void AddToPROJ4Cache(Proj4Cache cache, int srid, int other_srid) { -- AddToPROJ4SRSCache((PROJ4PortalCache *)cache, srid, other_srid) ; -+static int -+pjstrs_has_entry(const PjStrs *strs) -+{ -+ if ((strs->proj4text && strlen(strs->proj4text)) || -+ (strs->epsgtext && strlen(strs->epsgtext)) || -+ (strs->srtext && strlen(strs->srtext))) -+ return 1; -+ else -+ return 0; - } - -+static void -+pjstrs_pfree(PjStrs *strs) -+{ -+ if (strs->proj4text) -+ pfree(strs->proj4text); -+ if (strs->epsgtext) -+ pfree(strs->epsgtext); -+ if (strs->srtext) -+ pfree(strs->srtext); -+} -+ -+#if POSTGIS_PROJ_VERSION >= 60 -+static char* -+pgstrs_get_entry(const PjStrs *strs, int n) -+{ -+ switch (n) -+ { -+ case 0: -+ return strs->epsgtext; -+ case 1: -+ return strs->srtext; -+ case 2: -+ return strs->proj4text; -+ default: -+ return NULL; -+ } -+} -+#endif -+ -+/* -+* Utility function for GML reader that still -+* needs proj4text access -+*/ -+char * -+GetProj4String(int srid) -+{ -+ PjStrs strs; -+ char *proj4str; -+ memset(&strs, 0, sizeof(strs)); -+ strs = GetProjStringsSPI(srid); -+ proj4str = pstrdup(strs.proj4text); -+ pjstrs_pfree(&strs); -+ return proj4str; -+} - - /** -- * Add an entry to the local PROJ4 SRS cache. If we need to wrap around then -+ * Add an entry to the local PROJ SRS cache. If we need to wrap around then - * we must make sure the entry we choose to delete does not contain other_srid - * which is the definition for the other half of the transformation. - */ - static void --AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid) -+AddToPROJSRSCache(PROJPortalCache *PROJCache, int srid_from, int srid_to) - { - MemoryContext PJMemoryContext; -- projPJ projection = NULL; -- char *proj_str = NULL; -+ -+ PjStrs from_strs, to_strs; -+ char *pj_from_str, *pj_to_str; - - /* - ** Turn the SRID number into a proj4 string, by reading from spatial_ref_sys - ** or instantiating a magical value from a negative srid. - */ -- proj_str = GetProj4String(srid); -- if ( ! proj_str ) -- { -- elog(ERROR, "GetProj4String returned NULL for SRID (%d)", srid); -- } -+ from_strs = GetProjStrings(srid_from); -+ if (!pjstrs_has_entry(&from_strs)) -+ elog(ERROR, "got NULL for SRID (%d)", srid_from); -+ to_strs = GetProjStrings(srid_to); -+ if (!pjstrs_has_entry(&to_strs)) -+ elog(ERROR, "got NULL for SRID (%d)", srid_to); -+ -+#if POSTGIS_PROJ_VERSION < 60 -+ PJ* projection = malloc(sizeof(PJ)); -+ pj_from_str = from_strs.proj4text; -+ pj_to_str = to_strs.proj4text; -+ projection->pj_from = lwproj_from_string(pj_from_str); -+ projection->pj_to = lwproj_from_string(pj_to_str); - -- projection = lwproj_from_string(proj_str); -- if ( projection == NULL ) -- { -- char *pj_errstr = pj_strerrno(*pj_get_errno_ref()); -- if ( ! pj_errstr ) -- pj_errstr = ""; -+ if (!projection->pj_from) -+ elog(ERROR, -+ "could not form projection from 'srid=%d' to 'srid=%d'", -+ srid_from, srid_to); - -+ if (!projection->pj_to) -+ elog(ERROR, -+ "could not form projection from 'srid=%d' to 'srid=%d'", -+ srid_from, srid_to); -+#else -+ PJ* projection = NULL; -+ /* Try combinations of ESPG/SRTEXT/PROJ4TEXT until we find */ -+ /* one that gives us a usable transform. Note that we prefer */ -+ /* EPSG numbers over SRTEXT and SRTEXT over PROJ4TEXT */ -+ /* (3 entries * 3 entries = 9 combos) */ -+ uint32_t i; -+ for (i = 0; i < 9; i++) -+ { -+ pj_from_str = pgstrs_get_entry(&from_strs, i / 3); -+ pj_to_str = pgstrs_get_entry(&to_strs, i % 3); -+ if (!(pj_from_str && pj_to_str)) -+ continue; -+ projection = proj_create_crs_to_crs(NULL, pj_from_str, pj_to_str, NULL); -+ if (projection && !proj_errno(projection)) -+ break; -+ } -+ if (!projection) -+ { - elog(ERROR, -- "AddToPROJ4SRSCache: could not parse proj4 string '%s' %s", -- proj_str, pj_errstr); -+ "could not form projection from 'srid=%d' to 'srid=%d'", -+ srid_from, srid_to); - } -+#endif - - /* - * If the cache is already full then find the first entry -- * that doesn't contain other_srid and use this as the -- * subsequent value of PROJ4SRSCacheCount -+ * that doesn't contain our srids and use this as the -+ * subsequent value of PROJSRSCacheCount - */ -- if (PROJ4Cache->PROJ4SRSCacheCount == PROJ4_CACHE_ITEMS) -+ if (PROJCache->PROJSRSCacheCount == PROJ_CACHE_ITEMS) - { - bool found = false; -- int i; -- -- for (i = 0; i < PROJ4_CACHE_ITEMS; i++) -+ uint32_t i; -+ for (i = 0; i < PROJ_CACHE_ITEMS; i++) - { -- if (PROJ4Cache->PROJ4SRSCache[i].srid != other_srid && found == false) -+ if (found == false && -+ (PROJCache->PROJSRSCache[i].srid_from != srid_from || -+ PROJCache->PROJSRSCache[i].srid_to != srid_to)) - { -- POSTGIS_DEBUGF(3, "choosing to remove item from query cache with SRID %d and index %d", PROJ4Cache->PROJ4SRSCache[i].srid, i); -- -- DeleteFromPROJ4SRSCache(PROJ4Cache, PROJ4Cache->PROJ4SRSCache[i].srid); -- PROJ4Cache->PROJ4SRSCacheCount = i; -+ POSTGIS_DEBUGF(3, "choosing to remove item from query cache with SRIDs %d => %d and index %d", -+ PROJCache->PROJSRSCache[i].srid_from, -+ PROJCache->PROJSRSCache[i].srid_to, -+ i); -+ -+ DeleteFromPROJSRSCache(PROJCache, -+ PROJCache->PROJSRSCache[i].srid_from, -+ PROJCache->PROJSRSCache[i].srid_to); - -+ PROJCache->PROJSRSCacheCount = i; - found = true; - } - } -@@ -539,16 +716,21 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PRO - * Now create a memory context for this projection and - * store it in the backend hash - */ -- POSTGIS_DEBUGF(3, "adding SRID %d with proj4text \"%s\" to query cache at index %d", srid, proj_str, PROJ4Cache->PROJ4SRSCacheCount); -+ POSTGIS_DEBUGF(3, "adding transform %d => %d aka \"%s\" => \"%s\" to query cache at index %d", -+ srid_from, srid_to, pj_from_str, pj_to_str, PROJCache->PROJSRSCacheCount); -+ -+ /* Free the projection strings */ -+ pjstrs_pfree(&from_strs); -+ pjstrs_pfree(&to_strs); - - #if POSTGIS_PGSQL_VERSION < 96 - PJMemoryContext = MemoryContextCreate(T_AllocSetContext, 8192, -- &PROJ4SRSCacheContextMethods, -- PROJ4Cache->PROJ4SRSCacheContext, -- "PostGIS PROJ4 PJ Memory Context"); -+ &PROJSRSCacheContextMethods, -+ PROJCache->PROJSRSCacheContext, -+ "PostGIS PROJ PJ Memory Context"); - #else -- PJMemoryContext = AllocSetContextCreate(PROJ4Cache->PROJ4SRSCacheContext, -- "PostGIS PROJ4 PJ Memory Context", -+ PJMemoryContext = AllocSetContextCreate(PROJCache->PROJSRSCacheContext, -+ "PostGIS PROJ PJ Memory Context", - ALLOCSET_SMALL_SIZES); - - /* PgSQL comments suggest allocating callback in the context */ -@@ -557,7 +739,7 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PRO - { - MemoryContextCallback *callback = MemoryContextAlloc(PJMemoryContext, sizeof(MemoryContextCallback)); - callback->arg = (void*)PJMemoryContext; -- callback->func = PROJ4SRSCacheDelete; -+ callback->func = PROJSRSCacheDelete; - MemoryContextRegisterResetCallback(PJMemoryContext, callback); - } - #endif -@@ -574,43 +756,37 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PRO - - AddPJHashEntry(PJMemoryContext, projection); - -- PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].srid = srid; -- PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection = projection; -- PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection_mcxt = PJMemoryContext; -- PROJ4Cache->PROJ4SRSCacheCount++; -- -- /* Free the projection string */ -- pfree(proj_str); -- --} -- --void DeleteFromPROJ4Cache(Proj4Cache cache, int srid) { -- DeleteFromPROJ4SRSCache((PROJ4PortalCache *)cache, srid) ; -+ PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_from = srid_from; -+ PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_to = srid_to; -+ PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection = projection; -+ PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection_mcxt = PJMemoryContext; -+ PROJCache->PROJSRSCacheCount++; - } - - --static void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid) -+static void -+DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, int srid_from, int srid_to) - { - /* - * Delete the SRID entry from the cache - */ -- -- int i; -- -- for (i = 0; i < PROJ4_CACHE_ITEMS; i++) -+ uint32_t i; -+ for (i = 0; i < PROJ_CACHE_ITEMS; i++) - { -- if (PROJ4Cache->PROJ4SRSCache[i].srid == srid) -+ if (PROJCache->PROJSRSCache[i].srid_from == srid_from && -+ PROJCache->PROJSRSCache[i].srid_to == srid_to) - { -- POSTGIS_DEBUGF(3, "removing query cache entry with SRID %d at index %d", srid, i); -+ POSTGIS_DEBUGF(3, "removing query cache entry with SRIDs %d => %d at index %d", srid_from, srid_to, i); - - /* -- * Zero out the entries and free the PROJ4 handle -+ * Zero out the entries and free the PROJ handle - * by deleting the memory context - */ -- MemoryContextDelete(PROJ4Cache->PROJ4SRSCache[i].projection_mcxt); -- PROJ4Cache->PROJ4SRSCache[i].projection = NULL; -- PROJ4Cache->PROJ4SRSCache[i].projection_mcxt = NULL; -- PROJ4Cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN; -+ MemoryContextDelete(PROJCache->PROJSRSCache[i].projection_mcxt); -+ PROJCache->PROJSRSCache[i].projection = NULL; -+ PROJCache->PROJSRSCache[i].projection_mcxt = NULL; -+ PROJCache->PROJSRSCache[i].srid_from = SRID_UNKNOWN; -+ PROJCache->PROJSRSCache[i].srid_to = SRID_UNKNOWN; - } - } - } -@@ -628,13 +804,13 @@ static void DeleteFromPROJ4SRSCache(PROJ - * since the method of determining the current installation - * path are different on older PostgreSQL versions. - */ --void SetPROJ4LibPath(void) -+void SetPROJLibPath(void) - { - char *path; - char *share_path; - const char **proj_lib_path; - -- if (!IsPROJ4LibPathSet) { -+ if (!IsPROJLibPathSet) { - - /* - * Get the sharepath and append /contrib/postgis/proj to form a suitable -@@ -649,91 +825,74 @@ void SetPROJ4LibPath(void) - *proj_lib_path = path; - - snprintf(path, MAXPGPATH - 1, "%s/contrib/postgis-%s.%s/proj", share_path, POSTGIS_MAJOR_VERSION, POSTGIS_MINOR_VERSION); -- -+#if POSTGIS_PROJ_VERSION < 60 - /* Set the search path for PROJ.4 */ - pj_set_searchpath(1, proj_lib_path); -- -+#else -+ /* Set the search path for PROJ */ -+ proj_context_set_search_paths(NULL, 1, proj_lib_path); -+#endif - /* Ensure we only do this once... */ -- IsPROJ4LibPathSet = true; -+ IsPROJLibPathSet = true; - } - } - --Proj4Cache GetPROJ4Cache(FunctionCallInfo fcinfo) { -- return (Proj4Cache)GetPROJ4SRSCache(fcinfo); --} - - int --GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2) -+GetPJUsingFCInfo(FunctionCallInfo fcinfo, int srid_from, int srid_to, PJ** pj) - { -- Proj4Cache *proj_cache = NULL; -+ PROJPortalCache *proj_cache = NULL; - - /* Set the search path if we haven't already */ -- SetPROJ4LibPath(); -+ SetPROJLibPath(); - - /* Look up the spatial_ref_sys schema if we haven't already */ -- postgis_initialize_cache(fcinfo); -+ SetSpatialRefSysSchema(fcinfo); - - /* get or initialize the cache for this round */ -- proj_cache = GetPROJ4Cache(fcinfo); -- if ( !proj_cache ) -+ proj_cache = GetPROJSRSCache(fcinfo); -+ if (!proj_cache) - return LW_FAILURE; - - /* Add the output srid to the cache if it's not already there */ -- if (!IsInPROJ4Cache(proj_cache, srid1)) -- AddToPROJ4Cache(proj_cache, srid1, srid2); -- -- /* Add the input srid to the cache if it's not already there */ -- if (!IsInPROJ4Cache(proj_cache, srid2)) -- AddToPROJ4Cache(proj_cache, srid2, srid1); -+ if (!IsInPROJSRSCache(proj_cache, srid_from, srid_to)) -+ AddToPROJSRSCache(proj_cache, srid_from, srid_to); - - /* Get the projections */ -- *pj1 = GetProjectionFromPROJ4Cache(proj_cache, srid1); -- *pj2 = GetProjectionFromPROJ4Cache(proj_cache, srid2); -+ *pj = GetProjectionFromPROJCache(proj_cache, srid_from, srid_to); - - return LW_SUCCESS; - } - --int --spheroid_init_from_srid(FunctionCallInfo fcinfo, int srid, SPHEROID *s) --{ -- projPJ pj1, pj2; --#if POSTGIS_PROJ_VERSION >= 48 -- double major_axis, minor_axis, eccentricity_squared; --#endif -- -- if ( GetProjectionsUsingFCInfo(fcinfo, srid, srid, &pj1, &pj2) == LW_FAILURE) -- return LW_FAILURE; - -- if ( ! pj_is_latlong(pj1) ) -- return LW_FAILURE; -- --#if POSTGIS_PROJ_VERSION >= 48 -- /* For newer versions of Proj we can pull the spheroid paramaeters and initialize */ -- /* using them */ -- pj_get_spheroid_defn(pj1, &major_axis, &eccentricity_squared); -- minor_axis = major_axis * sqrt(1-eccentricity_squared); -- spheroid_init(s, major_axis, minor_axis); -+static int -+proj_pj_is_latlong(const PJ* pj) -+{ -+#if POSTGIS_PROJ_VERSION < 60 -+ return pj_is_latlong(pj->pj_from); - #else -- /* For old versions of Proj we cannot lookup the spheroid parameters from the API */ -- /* So we use the WGS84 parameters (boo!) */ -- spheroid_init(s, WGS84_MAJOR_AXIS, WGS84_MINOR_AXIS); -+ PJ_TYPE pj_type = proj_get_type(proj_get_source_crs(NULL, pj)); -+ return (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS) || -+ (pj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS); - #endif -- -- return LW_SUCCESS; - } - --void srid_is_latlong(FunctionCallInfo fcinfo, int srid) -+static int -+srid_is_latlong(FunctionCallInfo fcinfo, int srid) - { -- projPJ pj1; -- projPJ pj2; -- -- if ( srid == SRID_DEFAULT || srid == SRID_UNKNOWN ) -- return; -+ PJ* pj; -+ if ( GetPJUsingFCInfo(fcinfo, srid, srid, &pj) == LW_FAILURE) -+ return LW_FALSE; -+ return proj_pj_is_latlong(pj); -+} - -- if ( GetProjectionsUsingFCInfo(fcinfo, srid, srid, &pj1, &pj2) == LW_FAILURE) -+void -+srid_check_latlong(FunctionCallInfo fcinfo, int srid) -+{ -+ if (srid == SRID_DEFAULT || srid == SRID_UNKNOWN) - return; - -- if ( pj_is_latlong(pj1) ) -+ if (srid_is_latlong(fcinfo, srid)) - return; - - ereport(ERROR, ( -@@ -741,14 +900,10 @@ void srid_is_latlong(FunctionCallInfo fc - errmsg("Only lon/lat coordinate systems are supported in geography."))); - } - -- --srs_precision srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precision) -+srs_precision -+srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precision) - { -- projPJ pj1; -- projPJ pj2; -- - srs_precision sp; -- - sp.precision_xy = precision; - sp.precision_z = precision; - sp.precision_m = precision; -@@ -756,10 +911,7 @@ srs_precision srid_axis_precision(Functi - if ( srid == SRID_UNKNOWN ) - return sp; - -- if ( GetProjectionsUsingFCInfo(fcinfo, srid, srid, &pj1, &pj2) == LW_FAILURE) -- return sp; -- -- if ( pj_is_latlong(pj1) ) -+ if ( srid_is_latlong(fcinfo, srid) ) - { - sp.precision_xy += 5; - return sp; -@@ -767,3 +919,59 @@ srs_precision srid_axis_precision(Functi - - return sp; - } -+ -+int -+spheroid_init_from_srid(FunctionCallInfo fcinfo, int srid, SPHEROID *s) -+{ -+ PJ* pj; -+#if POSTGIS_PROJ_VERSION >= 60 -+ double out_semi_major_metre, out_semi_minor_metre, out_inv_flattening; -+ int out_is_semi_minor_computed; -+ PJ *pj_ellps, *pj_crs; -+#elif POSTGIS_PROJ_VERSION >= 48 -+ double major_axis, minor_axis, eccentricity_squared; -+#endif -+ -+ if ( GetPJUsingFCInfo(fcinfo, srid, srid, &pj) == LW_FAILURE) -+ return LW_FAILURE; -+ -+#if POSTGIS_PROJ_VERSION >= 60 -+ if (!proj_pj_is_latlong(pj)) -+ return LW_FAILURE; -+ pj_crs = proj_get_source_crs(NULL, pj); -+ if (!pj_crs) -+ { -+ lwerror("%s: proj_get_source_crs returned NULL", __func__); -+ } -+ pj_ellps = proj_get_ellipsoid(NULL, pj_crs); -+ if (!pj_ellps) -+ { -+ proj_destroy(pj_crs); -+ lwerror("%s: proj_get_ellipsoid returned NULL", __func__); -+ } -+ proj_ellipsoid_get_parameters(NULL, pj_ellps, -+ &out_semi_major_metre, &out_semi_minor_metre, -+ &out_is_semi_minor_computed, &out_inv_flattening); -+ proj_destroy(pj_ellps); -+ proj_destroy(pj_crs); -+ spheroid_init(s, out_semi_major_metre, out_semi_minor_metre); -+ -+#elif POSTGIS_PROJ_VERSION >= 48 -+ if (!pj_is_latlong(pj->pj_from)) -+ return LW_FAILURE; -+ /* For newer versions of Proj we can pull the spheroid paramaeters and initialize */ -+ /* using them */ -+ pj_get_spheroid_defn(pj->pj_from, &major_axis, &eccentricity_squared); -+ minor_axis = major_axis * sqrt(1-eccentricity_squared); -+ spheroid_init(s, major_axis, minor_axis); -+ -+#else -+ if (!pj_is_latlong(pj->pj_from)) -+ return LW_FAILURE; -+ /* For old versions of Proj we cannot lookup the spheroid parameters from the API */ -+ /* So we use the WGS84 parameters (boo!) */ -+ spheroid_init(s, WGS84_MAJOR_AXIS, WGS84_MINOR_AXIS); -+#endif -+ -+ return LW_SUCCESS; -+} -diff -rupN postgis-2.5.5/libpgcommon/lwgeom_transform.h postgis-2.5.5-new/libpgcommon/lwgeom_transform.h ---- postgis-2.5.5/libpgcommon/lwgeom_transform.h 2020-08-15 20:43:43.000000000 +0200 -+++ postgis-2.5.5-new/libpgcommon/lwgeom_transform.h 2022-08-06 11:48:23.739708197 +0200 -@@ -10,9 +10,10 @@ - **********************************************************************/ - - #include "postgres.h" --#include "liblwgeom.h" -+#include "liblwgeom_internal.h" - #include "lwgeom_pg.h" - -+ - typedef struct srs_precision - { - int precision_xy; -@@ -20,23 +21,19 @@ typedef struct srs_precision - int precision_m; - } srs_precision; - --char* GetProj4StringSPI(int srid); --void SetPROJ4LibPath(void) ; -+char * GetProj4String(int srid); - - /** - * Opaque type to use in the projection cache API. - */ --typedef void *Proj4Cache ; -+typedef void *ProjCache ; - --void SetPROJ4LibPath(void); --Proj4Cache GetPROJ4Cache(FunctionCallInfo fcinfo) ; --bool IsInPROJ4Cache(Proj4Cache cache, int srid) ; --void AddToPROJ4Cache(Proj4Cache cache, int srid, int other_srid); --void DeleteFromPROJ4Cache(Proj4Cache cache, int srid) ; --projPJ GetProjectionFromPROJ4Cache(Proj4Cache cache, int srid); --int GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2); -+void SetPROJLibPath(void); -+bool IsInPROJCache(ProjCache cache, int srid_from, int srid_to); -+PJ* GetPJFromPROJCache(ProjCache cache, int srid_from, int srid_to); -+int GetPJUsingFCInfo(FunctionCallInfo fcinfo, int srid_from, int srid_to, PJ** pj); - int spheroid_init_from_srid(FunctionCallInfo fcinfo, int srid, SPHEROID *s); --void srid_is_latlong(FunctionCallInfo fcinfo, int srid); -+void srid_check_latlong(FunctionCallInfo fcinfo, int srid); - srs_precision srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precision); - - /** -diff -rupN postgis-2.5.5/macros/ac_proj4_version.m4 postgis-2.5.5-new/macros/ac_proj4_version.m4 ---- postgis-2.5.5/macros/ac_proj4_version.m4 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/macros/ac_proj4_version.m4 2022-08-06 11:48:23.740708197 +0200 -@@ -14,29 +14,53 @@ dnl Return the PROJ.4 version number - dnl - - AC_DEFUN([AC_PROJ_VERSION], [ -- AC_RUN_IFELSE( -- [AC_LANG_PROGRAM([ -- #ifdef HAVE_STDINT_H -- #include -- #endif -- #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1 -- #include "proj_api.h" -- ], -- [ -- FILE *fp; - -- fp = fopen("conftest.out", "w"); -- fprintf(fp, "%d\n", PJ_VERSION); -- fclose(fp)]) -- ], -- [ -- dnl The program ran successfully, so return the version number in the form MAJORMINOR -- $1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'` -- ], -- [ -- dnl The program failed so return an empty variable -- $1="" -- ] -- ) -+ AC_CHECK_HEADER([proj.h], [ -+ dnl Proj >= 6 include and version string -+ AC_RUN_IFELSE([ -+ AC_LANG_PROGRAM([ -+ #ifdef HAVE_STDINT_H -+ #include -+ #endif -+ #include "proj.h" -+ ],[ -+ FILE *fp; -+ int vernum; -+ -+ fp = fopen("conftest.out", "w"); -+ vernum = (100 * PROJ_VERSION_MAJOR) + (10 * PROJ_VERSION_MINOR) + PROJ_VERSION_PATCH; -+ fprintf(fp, "%d\n", vernum); -+ fclose(fp); -+ ]) -+ ],[ -+ dnl The program ran successfully, so return the version number in the form MAJORMINOR -+ $1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'` -+ ],[ -+ dnl The program failed so return an empty variable -+ $1="" -+ ]) -+ ],[ -+ dnl Proj < 6 include and version string -+ AC_RUN_IFELSE( -+ [AC_LANG_PROGRAM([ -+ #ifdef HAVE_STDINT_H -+ #include -+ #endif -+ #include "proj_api.h" -+ ],[ -+ FILE *fp; -+ -+ fp = fopen("conftest.out", "w"); -+ fprintf(fp, "%d\n", PJ_VERSION); -+ fclose(fp); -+ ]) -+ ],[ -+ dnl The program ran successfully, so return the version number in the form MAJORMINOR -+ $1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'` -+ ],[ -+ dnl The program failed so return an empty variable -+ $1="" -+ ]) -+ ]) - ]) - -diff -rupN postgis-2.5.5/postgis/geography_inout.c postgis-2.5.5-new/postgis/geography_inout.c ---- postgis-2.5.5/postgis/geography_inout.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/geography_inout.c 2022-08-06 11:48:23.740708197 +0200 -@@ -172,7 +172,7 @@ Datum geography_in(PG_FUNCTION_ARGS) - } - - /* Error on any SRID != default */ -- srid_is_latlong(fcinfo, lwgeom->srid); -+ srid_check_latlong(fcinfo, lwgeom->srid); - - /* Convert to gserialized */ - g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod); -@@ -568,7 +568,7 @@ Datum geography_from_text(PG_FUNCTION_AR - PG_PARSER_ERROR(lwg_parser_result); - - /* Error on any SRID != default */ -- srid_is_latlong(fcinfo, lwg_parser_result.geom->srid); -+ srid_check_latlong(fcinfo, lwg_parser_result.geom->srid); - - /* Clean up string */ - pfree(wkt); -@@ -596,7 +596,7 @@ Datum geography_from_binary(PG_FUNCTION_ - lwpgerror("Unable to parse WKB"); - - /* Error on any SRID != default */ -- srid_is_latlong(fcinfo, lwgeom->srid); -+ srid_check_latlong(fcinfo, lwgeom->srid); - - gser = gserialized_geography_from_lwgeom(lwgeom, -1); - lwgeom_free(lwgeom); -@@ -622,7 +622,7 @@ Datum geography_from_geometry(PG_FUNCTIO - } - - /* Error on any SRID != default */ -- srid_is_latlong(fcinfo, lwgeom->srid); -+ srid_check_latlong(fcinfo, lwgeom->srid); - - /* Force the geometry to have valid geodetic coordinate range. */ - lwgeom_nudge_geodetic(lwgeom); -@@ -686,7 +686,7 @@ Datum geography_recv(PG_FUNCTION_ARGS) - lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL); - - /* Error on any SRID != default */ -- srid_is_latlong(fcinfo, lwgeom->srid); -+ srid_check_latlong(fcinfo, lwgeom->srid); - - g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod); - -diff -rupN postgis-2.5.5/postgis/geography_measurement.c postgis-2.5.5-new/postgis/geography_measurement.c ---- postgis-2.5.5/postgis/geography_measurement.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/geography_measurement.c 2022-08-06 11:48:23.741708197 +0200 -@@ -40,7 +40,7 @@ - #include "geography_measurement_trees.h" /* For circ_tree caching */ - #include "lwgeom_transform.h" /* For SRID functions */ - --#if PROJ_GEODESIC -+#ifdef PROJ_GEODESIC - /* round to 10 nm precision */ - #define INVMINDIST 1.0e8 - #else -@@ -532,7 +532,7 @@ Datum geography_area(PG_FUNCTION_ARGS) - else - lwgeom_calculate_gbox_geodetic(lwgeom, &gbox); - --#if ! PROJ_GEODESIC -+#ifndef PROJ_GEODESIC - /* Test for cases that are currently not handled by spheroid code */ - if ( use_spheroid ) - { -@@ -543,7 +543,7 @@ Datum geography_area(PG_FUNCTION_ARGS) - if ( gbox.zmax > 0.0 && gbox.zmin < 0.0 ) - use_spheroid = LW_FALSE; - } --#endif /* if ! PROJ_GEODESIC */ -+#endif /* ifndef PROJ_GEODESIC */ - - /* User requests spherical calculation, turn our spheroid into a sphere */ - if ( ! use_spheroid ) -diff -rupN postgis-2.5.5/postgis/gserialized_gist_2d.c postgis-2.5.5-new/postgis/gserialized_gist_2d.c ---- postgis-2.5.5/postgis/gserialized_gist_2d.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/gserialized_gist_2d.c 2022-08-06 11:48:23.742708197 +0200 -@@ -60,6 +60,7 @@ - #endif - - #include /* For FLT_MAX */ -+#include - - /* - ** When is a node split not so good? If more than 90% of the entries -diff -rupN postgis-2.5.5/postgis/gserialized_gist_nd.c postgis-2.5.5-new/postgis/gserialized_gist_nd.c ---- postgis-2.5.5/postgis/gserialized_gist_nd.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/gserialized_gist_nd.c 2022-08-06 11:48:23.743708197 +0200 -@@ -52,6 +52,7 @@ - #include "geography.h" - - #include -+#include - - - /* Fall back to older finite() if necessary */ -diff -rupN postgis-2.5.5/postgis/gserialized_spgist_2d.c postgis-2.5.5-new/postgis/gserialized_spgist_2d.c ---- postgis-2.5.5/postgis/gserialized_spgist_2d.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/gserialized_spgist_2d.c 2022-08-06 11:48:23.744708197 +0200 -@@ -81,6 +81,7 @@ - #include "lwgeom_pg.h" /* For debugging macros. */ - #include /* For utility functions. */ - #include /* For debugging macros. */ -+#include - - /* - ** SP-GiST 2D index function prototypes -diff -rupN postgis-2.5.5/postgis/gserialized_typmod.c postgis-2.5.5-new/postgis/gserialized_typmod.c ---- postgis-2.5.5/postgis/gserialized_typmod.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/gserialized_typmod.c 2022-08-06 11:48:23.744708197 +0200 -@@ -295,7 +295,7 @@ Datum geography_typmod_in(PG_FUNCTION_AR - int32 typmod = gserialized_typmod_in(arr, LW_TRUE); - int srid = TYPMOD_GET_SRID(typmod); - /* Check the SRID is legal (geographic coordinates) */ -- srid_is_latlong(fcinfo, srid); -+ srid_check_latlong(fcinfo, srid); - - PG_RETURN_INT32(typmod); - } -diff -rupN postgis-2.5.5/postgis/lwgeom_in_gml.c postgis-2.5.5-new/postgis/lwgeom_in_gml.c ---- postgis-2.5.5/postgis/lwgeom_in_gml.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/lwgeom_in_gml.c 2022-08-06 11:48:23.745708197 +0200 -@@ -297,36 +297,68 @@ static xmlNodePtr get_xlink_node(xmlNode - } - - -+ - /** -- * Use Proj4 to reproject a given POINTARRAY -+ * Use Proj to reproject a given POINTARRAY - */ -+ -+#if POSTGIS_PROJ_VERSION < 60 -+ - static POINTARRAY* gml_reproject_pa(POINTARRAY *pa, int srid_in, int srid_out) - { -- projPJ in_pj, out_pj; -+ PJ pj; - char *text_in, *text_out; - - if (srid_in == SRID_UNKNOWN) return pa; /* nothing to do */ - if (srid_out == SRID_UNKNOWN) gml_lwpgerror("invalid GML representation", 3); - -- text_in = GetProj4StringSPI(srid_in); -- text_out = GetProj4StringSPI(srid_out); -+ text_in = GetProj4String(srid_in); -+ text_out = GetProj4String(srid_out); - -- in_pj = lwproj_from_string(text_in); -- out_pj = lwproj_from_string(text_out); -+ pj.pj_from = lwproj_from_string(text_in); -+ pj.pj_to = lwproj_from_string(text_out); - - lwfree(text_in); - lwfree(text_out); - -- if ( ptarray_transform(pa, in_pj, out_pj) == LW_FAILURE ) -+ if ( ptarray_transform(pa, &pj) == LW_FAILURE ) - { - elog(ERROR, "gml_reproject_pa: reprojection failed"); - } - -- pj_free(in_pj); -- pj_free(out_pj); -+ pj_free(pj.pj_from); -+ pj_free(pj.pj_to); -+ -+ return pa; -+} -+#else -+/* -+ * TODO: rework GML projection handling to skip the spatial_ref_sys -+ * lookups, and use the Proj 6+ EPSG catalogue and built-in SRID -+ * lookups directly. Drop this ugly hack. -+ */ -+static POINTARRAY* gml_reproject_pa(POINTARRAY *pa, int srid_in, int srid_out) -+{ -+ PJ *pj; -+ char text_in[32]; -+ char text_out[32]; -+ -+ if (srid_in == SRID_UNKNOWN) return pa; /* nothing to do */ -+ if (srid_out == SRID_UNKNOWN) gml_lwpgerror("invalid GML representation", 3); -+ -+ snprintf(text_in, 32, "EPSG:%d", srid_in); -+ snprintf(text_out, 32, "EPSG:%d", srid_out); -+ pj = proj_create_crs_to_crs(NULL, text_in, text_out, NULL); -+ -+ if (ptarray_transform(pa, pj) == LW_FAILURE) -+ { -+ elog(ERROR, "gml_reproject_pa: reprojection failed"); -+ } -+ proj_destroy(pj); - - return pa; - } -+#endif /* POSTGIS_PROJ_VERSION */ - - - /** -diff -rupN postgis-2.5.5/postgis/lwgeom_spheroid.c postgis-2.5.5-new/postgis/lwgeom_spheroid.c ---- postgis-2.5.5/postgis/lwgeom_spheroid.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/lwgeom_spheroid.c 2022-08-06 11:48:23.745708197 +0200 -@@ -440,7 +440,7 @@ Datum LWGEOM_length_ellipsoid_linestring - * (if deltaX is 1 degrees, then that distance represents 1/360 of a circle of radius S.) - * - * -- * Parts taken from PROJ4 - geodetic_to_geocentric() (for calculating Rn) -+ * Parts taken from PROJ - geodetic_to_geocentric() (for calculating Rn) - * - * remember that lat1/long1/lat2/long2 are comming in a *RADIANS* not degrees. - * -diff -rupN postgis-2.5.5/postgis/lwgeom_transform.c postgis-2.5.5-new/postgis/lwgeom_transform.c ---- postgis-2.5.5/postgis/lwgeom_transform.c 2020-08-15 20:43:44.000000000 +0200 -+++ postgis-2.5.5-new/postgis/lwgeom_transform.c 2022-08-06 11:48:23.746708197 +0200 -@@ -47,23 +47,23 @@ Datum postgis_proj_version(PG_FUNCTION_A - PG_FUNCTION_INFO_V1(transform); - Datum transform(PG_FUNCTION_ARGS) - { -- GSERIALIZED *geom; -- GSERIALIZED *result=NULL; -- LWGEOM *lwgeom; -- projPJ input_pj, output_pj; -- int32 output_srid, input_srid; -+ GSERIALIZED* geom; -+ GSERIALIZED* result=NULL; -+ LWGEOM* lwgeom; -+ PJ* pj; -+ int32 srid_to, srid_from; - -- output_srid = PG_GETARG_INT32(1); -- if (output_srid == SRID_UNKNOWN) -+ srid_to = PG_GETARG_INT32(1); -+ if (srid_to == SRID_UNKNOWN) - { - elog(ERROR, "%d is an invalid target SRID", SRID_UNKNOWN); - PG_RETURN_NULL(); - } - - geom = PG_GETARG_GSERIALIZED_P_COPY(0); -- input_srid = gserialized_get_srid(geom); -+ srid_from = gserialized_get_srid(geom); - -- if ( input_srid == SRID_UNKNOWN ) -+ if ( srid_from == SRID_UNKNOWN ) - { - PG_FREE_IF_COPY(geom, 0); - elog(ERROR, "Input geometry has unknown (%d) SRID", SRID_UNKNOWN); -@@ -71,10 +71,10 @@ Datum transform(PG_FUNCTION_ARGS) - } - - /* Input SRID and output SRID are equal, noop */ -- if ( input_srid == output_srid ) -+ if ( srid_from == srid_to ) - PG_RETURN_POINTER(geom); - -- if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE ) -+ if ( GetPJUsingFCInfo(fcinfo, srid_from, srid_to, &pj) == LW_FAILURE ) - { - PG_FREE_IF_COPY(geom, 0); - elog(ERROR, "Failure reading projections from spatial_ref_sys."); -@@ -83,8 +83,8 @@ Datum transform(PG_FUNCTION_ARGS) - - /* now we have a geometry, and input/output PJ structs. */ - lwgeom = lwgeom_from_gserialized(geom); -- lwgeom_transform(lwgeom, input_pj, output_pj); -- lwgeom->srid = output_srid; -+ lwgeom_transform(lwgeom, pj); -+ lwgeom->srid = srid_to; - - /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */ - if ( lwgeom->bbox ) -@@ -110,96 +110,57 @@ Datum transform(PG_FUNCTION_ARGS) - PG_FUNCTION_INFO_V1(transform_geom); - Datum transform_geom(PG_FUNCTION_ARGS) - { -- GSERIALIZED *geom; -- GSERIALIZED *result=NULL; -- LWGEOM *lwgeom; -- projPJ input_pj, output_pj; -- char *input_proj4, *output_proj4; -- text *input_proj4_text; -- text *output_proj4_text; -- int32 result_srid ; -- char *pj_errstr; -+ GSERIALIZED *gser, *gser_result=NULL; -+ LWGEOM *geom; -+ char *input_srs, *output_srs; -+ int32 result_srid; -+ int rv; - -- result_srid = PG_GETARG_INT32(3); -- geom = PG_GETARG_GSERIALIZED_P_COPY(0); -+ /* Take a copy, since we will be altering the coordinates */ -+ gser = PG_GETARG_GSERIALIZED_P_COPY(0); - - /* Set the search path if we haven't already */ -- SetPROJ4LibPath(); -- -- /* Read the arguments */ -- input_proj4_text = (PG_GETARG_TEXT_P(1)); -- output_proj4_text = (PG_GETARG_TEXT_P(2)); -+ SetPROJLibPath(); - - /* Convert from text to cstring for libproj */ -- input_proj4 = text_to_cstring(input_proj4_text); -- output_proj4 = text_to_cstring(output_proj4_text); -- -- /* make input and output projection objects */ -- input_pj = lwproj_from_string(input_proj4); -- if ( input_pj == NULL ) -- { -- pj_errstr = pj_strerrno(*pj_get_errno_ref()); -- if ( ! pj_errstr ) pj_errstr = ""; -- -- /* we need this for error reporting */ -- /* pfree(input_proj4); */ -- pfree(output_proj4); -- pfree(geom); -- -- elog(ERROR, -- "transform_geom: could not parse proj4 string '%s' %s", -- input_proj4, pj_errstr); -- PG_RETURN_NULL(); -- } -- pfree(input_proj4); -+ input_srs = text_to_cstring(PG_GETARG_TEXT_P(1)); -+ output_srs = text_to_cstring(PG_GETARG_TEXT_P(2)); -+ result_srid = PG_GETARG_INT32(3); - -- output_pj = lwproj_from_string(output_proj4); -+ /* now we have a geometry, and input/output PJ structs. */ -+ geom = lwgeom_from_gserialized(gser); -+ rv = lwgeom_transform_from_str(geom, input_srs, output_srs); -+ pfree(input_srs); -+ pfree(output_srs); - -- if ( output_pj == NULL ) -+ if (rv == LW_FAILURE) - { -- pj_errstr = pj_strerrno(*pj_get_errno_ref()); -- if ( ! pj_errstr ) pj_errstr = ""; -- -- /* we need this for error reporting */ -- /* pfree(output_proj4); */ -- pj_free(input_pj); -- pfree(geom); -- -- elog(ERROR, -- "transform_geom: couldn't parse proj4 output string: '%s': %s", -- output_proj4, pj_errstr); -+ elog(ERROR, "coordinate transformation failed"); - PG_RETURN_NULL(); - } -- pfree(output_proj4); -- -- /* now we have a geometry, and input/output PJ structs. */ -- lwgeom = lwgeom_from_gserialized(geom); -- lwgeom_transform(lwgeom, input_pj, output_pj); -- lwgeom->srid = result_srid; -- -- /* clean up */ -- pj_free(input_pj); -- pj_free(output_pj); - - /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */ -- if ( lwgeom->bbox ) -- { -- lwgeom_refresh_bbox(lwgeom); -- } -+ geom->srid = result_srid; -+ if (geom->bbox) -+ lwgeom_refresh_bbox(geom); -+ -+ gser_result = geometry_serialize(geom); -+ lwgeom_free(geom); -+ PG_FREE_IF_COPY(gser, 0); - -- result = geometry_serialize(lwgeom); -- -- lwgeom_free(lwgeom); -- PG_FREE_IF_COPY(geom, 0); -- -- PG_RETURN_POINTER(result); /* new geometry */ -+ PG_RETURN_POINTER(gser_result); /* new geometry */ - } - - - PG_FUNCTION_INFO_V1(postgis_proj_version); - Datum postgis_proj_version(PG_FUNCTION_ARGS) - { -+#if POSTGIS_PROJ_VERSION < 60 - const char *ver = pj_get_release(); - text *result = cstring_to_text(ver); -+#else -+ PJ_INFO pji = proj_info(); -+ text *result = cstring_to_text(pji.version); -+#endif - PG_RETURN_POINTER(result); - } diff --git a/sources b/sources deleted file mode 100644 index 4921b68..0000000 --- a/sources +++ /dev/null @@ -1,2 +0,0 @@ -SHA512 (postgis-3.5.3-en.pdf) = 69e162ea657a3bce2fb139ebeb9bd212ac646cb83027345eab9677609160a365d3ecdaa2995eb494054fc4667016a069afdbdbbd1cc56ff407fac05fd8306fa0 -SHA512 (postgis-3.5.3.tar.gz) = c27f57f0dbf3938648fe16dcaaff28530de6a51c13c481cb78163a51a292f3d77620485cd31e79cd01be675b5dca97129c50c562f68d6d864c822ea7359d754f