Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: post...@packages.debian.org
Control: affects -1 + src:postgis

[ Reason ]
The recent stable update to fix #1031392 introduced a regression as reported in 
#1035921.

[ Impact ]
Incorrect axis order for some projections.

[ Tests ]
Upstream test suite. Manually tested the updated package to verify the fix.

[ Risks ]
Low, leaf package.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Two additional upstream changes were required to fix the regression, one from 
before the patch in the previous stable update, and one following it.

[ Other info ]
N/A
diff -Nru postgis-3.1.1+dfsg/debian/changelog 
postgis-3.1.1+dfsg/debian/changelog
--- postgis-3.1.1+dfsg/debian/changelog 2023-02-16 19:00:56.000000000 +0100
+++ postgis-3.1.1+dfsg/debian/changelog 2023-05-11 10:39:28.000000000 +0200
@@ -1,3 +1,10 @@
+postgis (3.1.1+dfsg-1+deb11u2) bullseye; urgency=medium
+
+  * Add upstream patches to fix axis order regession.
+    (closes: #1035921)
+
+ -- Bas Couwenberg <sebas...@debian.org>  Thu, 11 May 2023 10:39:28 +0200
+
 postgis (3.1.1+dfsg-1+deb11u1) bullseye; urgency=medium
 
   * Update branch in gbp.conf & Vcs-Git URL.
diff -Nru 
postgis-3.1.1+dfsg/debian/patches/0001-Flip-N-E-systems-to-E-N-and-geodetic-systems-to-Lon-.patch
 
postgis-3.1.1+dfsg/debian/patches/0001-Flip-N-E-systems-to-E-N-and-geodetic-systems-to-Lon-.patch
--- 
postgis-3.1.1+dfsg/debian/patches/0001-Flip-N-E-systems-to-E-N-and-geodetic-systems-to-Lon-.patch
   1970-01-01 01:00:00.000000000 +0100
+++ 
postgis-3.1.1+dfsg/debian/patches/0001-Flip-N-E-systems-to-E-N-and-geodetic-systems-to-Lon-.patch
   2023-05-11 10:39:16.000000000 +0200
@@ -0,0 +1,146 @@
+Description: Flip N/E systems to E/N and geodetic systems to Lon/Lat, while 
leaving Polar systems as-is, references #4949, 3.1 branch
+Author: Paul Ramsey <pram...@cleverelephant.ca>
+Origin: 
https://trac.osgeo.org/postgis/changeset/8baf0b07b26df12d246c82bdae8ecd77371f3d24/git
+Bug: https://trac.osgeo.org/postgis/ticket/4949
+Bug-Debian: https://bugs.debian.org/1035921
+
+--- a/liblwgeom/lwgeom_transform.c
++++ b/liblwgeom/lwgeom_transform.c
+@@ -261,43 +261,63 @@ proj_cs_get_simplecs(const PJ *pj_crs)
+       return NULL;
+ }
+ 
++#define STR_EQUALS(A, B) strcmp((A), (B)) == 0
++#define STR_IEQUALS(A, B) (strcasecmp((A), (B)) == 0)
++#define STR_ISTARTS(A, B) (strncasecmp((A), (B), strlen((B))) == 0)
++
+ static uint8_t
+ proj_crs_is_swapped(const PJ *pj_crs)
+ {
+-      PJ *pj_cs;
+-      uint8_t rv = LW_FALSE;
++    int axis_count;
++    PJ *pj_cs = proj_cs_get_simplecs(pj_crs);
++    if (!pj_cs)
++        lwerror("%s: proj_cs_get_simplecs returned NULL", __func__);
++
++    axis_count = proj_cs_get_axis_count(NULL, pj_cs);
++    if (axis_count >= 2)
++    {
++        const char *out_name1, *out_abbrev1, *out_direction1;
++        const char *out_name2, *out_abbrev2, *out_direction2;
++        /* Read first axis */
++        proj_cs_get_axis_info(NULL,
++            pj_cs, 0,
++            &out_name1, &out_abbrev1, &out_direction1,
++            NULL, NULL, NULL, NULL);
++        /* Read second axis */
++        proj_cs_get_axis_info(NULL,
++            pj_cs, 1,
++            &out_name2, &out_abbrev2, &out_direction2,
++            NULL, NULL, NULL, NULL);
++
++        proj_destroy(pj_cs);
++
++        /* Directions agree, this is a northing/easting CRS, so reverse it */
++        if(out_direction1 && STR_IEQUALS(out_direction1, "north") &&
++           out_direction2 && STR_IEQUALS(out_direction2, "east") )
++        {
++            return LW_TRUE;
++        }
++
++        /* Oddball case? Both axes north / both axes south, swap */
++        if(out_direction1 && out_direction2 &&
++           ((STR_IEQUALS(out_direction1, "north") && 
STR_IEQUALS(out_direction2, "north")) ||
++            (STR_IEQUALS(out_direction1, "south") && 
STR_IEQUALS(out_direction2, "south"))) &&
++           out_name1 && STR_ISTARTS(out_name1, "northing")  &&
++           out_name2 && STR_ISTARTS(out_name2, "easting"))
++        {
++            return LW_TRUE;
++        }
++
++        /* Any lat/lon system with Lat in first axis gets swapped */
++        if (STR_ISTARTS(out_abbrev1, "Lat"))
++            return LW_TRUE;
++
++        return LW_FALSE;
++    }
+ 
+-      pj_cs = proj_cs_get_simplecs(pj_crs);
+-      if (!pj_cs) {
+-              lwerror("%s: proj_cs_get_simplecs returned NULL", __func__);
+-      }
+-      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 */
+-              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);
+-
+-              /* Only swap Lat/Lon systems */
+-              /* Use whatever ordering planar systems default to */
+-              if (strcasecmp(out_abbrev, "Lat") == 0)
+-                      rv = LW_TRUE;
+-              else
+-                      rv = LW_FALSE;
+-      }
+-      proj_destroy(pj_cs);
+-      return rv;
++    /* Failed the axis count test, leave quietly */
++    proj_destroy(pj_cs);
++    return LW_FALSE;
+ }
+ 
+ LWPROJ *
+--- a/regress/core/tickets.sql
++++ b/regress/core/tickets.sql
+@@ -1318,3 +1318,25 @@ SELECT '#4727', _ST_DistanceTree('SRID=4
+ SELECT '#4796', 
st_astext(st_snaptogrid(st_normalize(st_simplifypreservetopology('MULTISURFACE(((178632.044
 397744.007,178631.118 397743.786,178646.399 397679.574,178693.864 
397690.889,178698.958 397669.487,178700.206 397669.784,178758.532 
397683.689,178748.351 397726.468,178752.199 397727.384,178748.782 
397741.904,178744.897 397740.98,178738.157 397769.303,178632.044 
397744.007)))'::geometry,1)),1));
+ 
+ SELECT '#4812', st_srid('SRID=999999;POINT(1 1)'::geometry);
++
++-- New Zealand forward -- SRID=2193;POINT(1766289 5927325)
++SELECT '#4949', 'NZ forward', ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=4326;POINT(174.863597538742 -36.785298415230315)'::geometry, 
2193),0.1));
++--- New Zealand inverse (opposite EPSG order) -- SRID=4326;POINT(174.863598 
-36.785298)
++SELECT '#4949', 'NZ inverse', ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=2193;POINT(1766289 5927325)'::geometry, 4326),0.000001));
++-- British Columbia forward (respect EPSG order) -- 
SRID=3005;POINT(1286630.44 561883.98)
++SELECT '#4949', 'BC forward', ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=4269;POINT(-122 50)'::geometry, 3005),0.01));
++-- British Columbia inverse (respect EPSG order) -- SRID=4269;POINT(-122 50)
++SELECT '#4949', 'BC inverse', ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=3005;POINT(1286630.44 561883.98)'::geometry, 4269),0.000001));
++--  North Pole LAEA Europe inverse -- SRID=4326;POINT(19.4921659 69.7902258)
++SELECT '#4949', 'North Pole LAEA inverse', 
ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=3575;POINT(370182 -2213980)'::geometry,4326),0.0000001));
++-- Polar Stereographic forward -- SRID=3413;POINT(2218082.1 -1409150)
++SELECT '#4949', 'Arctic Stereographic forward', 
ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=4326;POINT(12.572160  66.081084)'::geometry,3413),0.1));
++-- Antarctic Polar Stereographic -- SRID=3031;POINT(-2399498.7 3213318.5)
++SELECT '#4949', 'Antarctic Stereographic forward', 
ST_AsEWKT(ST_SnapToGrid(ST_Transform(
++  'SRID=4326;POINT(-36.75 -54.25)'::geometry, 3031),0.1));
+--- a/regress/core/tickets_expected
++++ b/regress/core/tickets_expected
+@@ -440,3 +440,10 @@ ERROR:  LWGEOM_addpoint: Invalid offset
+ #4727|0
+ #4796|POLYGON((178632 397744,178738 397769,178745 397741,178749 397742,178752 
397727,178748 397726,178759 397684,178699 397669,178694 397691,178646 
397680,178632 397744))
+ #4812|999999
++#4949|NZ forward|SRID=2193;POINT(1766289 5927325)
++#4949|NZ inverse|SRID=4326;POINT(174.863598 -36.785298)
++#4949|BC forward|SRID=3005;POINT(1286630.44 561883.98)
++#4949|BC inverse|SRID=4269;POINT(-122 50)
++#4949|North Pole LAEA inverse|SRID=4326;POINT(19.4921659 69.7902258)
++#4949|Arctic Stereographic forward|SRID=3413;POINT(2218082.1 -1409150)
++#4949|Antarctic Stereographic forward|SRID=3031;POINT(-2399498.7 3213318.5)
diff -Nru 
postgis-3.1.1+dfsg/debian/patches/0001-Handle-more-deeply-nested-CRS-objects-when-extractin.patch
 
postgis-3.1.1+dfsg/debian/patches/0001-Handle-more-deeply-nested-CRS-objects-when-extractin.patch
--- 
postgis-3.1.1+dfsg/debian/patches/0001-Handle-more-deeply-nested-CRS-objects-when-extractin.patch
   1970-01-01 01:00:00.000000000 +0100
+++ 
postgis-3.1.1+dfsg/debian/patches/0001-Handle-more-deeply-nested-CRS-objects-when-extractin.patch
   2023-05-11 10:39:23.000000000 +0200
@@ -0,0 +1,92 @@
+Description: Handle more deeply nested CRS objects when extracting CS objects 
to find axis ordering. References #4817
+Author: Paul Ramsey <pram...@cleverelephant.ca>
+Origin: 
https://trac.osgeo.org/postgis/changeset/11efb9f0cdc71cf2bdc4850491218495a07b18ba/git
+Bug: https://trac.osgeo.org/postgis/ticket/4817
+Bug-Debian: https://bugs.debian.org/1035921
+
+--- a/liblwgeom/lwgeom_transform.c
++++ b/liblwgeom/lwgeom_transform.c
+@@ -211,34 +211,66 @@ projpj_from_string(const char *str1)
+ 
+ #else /* POSTGIS_PROJ_VERION >= 60 */
+ 
+-static uint8_t
+-proj_crs_is_swapped(const PJ *pj_crs)
++static PJ *
++proj_cs_get_simplecs(const PJ *pj_crs)
+ {
+-      PJ *pj_cs;
+-      uint8_t rv = LW_FALSE;
+-
++      PJ *pj_sub = NULL;
+       if (proj_get_type(pj_crs) == PJ_TYPE_COMPOUND_CRS)
+       {
+-              PJ *pj_horiz_crs = proj_crs_get_sub_crs(NULL, pj_crs, 0);
+-              if (!pj_horiz_crs)
+-                      lwerror("%s: proj_crs_get_sub_crs returned NULL", 
__func__);
+-              pj_cs = proj_crs_get_coordinate_system(NULL, pj_horiz_crs);
+-              proj_destroy(pj_horiz_crs);
++              /* Sub-CRS[0] is the horizontal component */
++              pj_sub = proj_crs_get_sub_crs(NULL, pj_crs, 0);
++              if (!pj_sub)
++                      lwerror("%s: proj_crs_get_sub_crs(0) returned NULL", 
__func__);
+       }
+       else if (proj_get_type(pj_crs) == PJ_TYPE_BOUND_CRS)
+       {
+-              PJ *pj_src_crs = proj_get_source_crs(NULL, pj_crs);
+-              if (!pj_src_crs)
++              pj_sub = proj_get_source_crs(NULL, pj_crs);
++              if (!pj_sub)
+                       lwerror("%s: proj_get_source_crs returned NULL", 
__func__);
+-              pj_cs = proj_crs_get_coordinate_system(NULL, pj_src_crs);
+-              proj_destroy(pj_src_crs);
+       }
+       else
+       {
+-              pj_cs = proj_crs_get_coordinate_system(NULL, pj_crs);
++              /* If this works, we have a CS so we can return */
++              pj_sub = proj_crs_get_coordinate_system(NULL, pj_crs);
++              if (pj_sub)
++                      return pj_sub;
++      }
++
++      /* Only sub-components of the Compound or Bound CRS's get here */
++      /* If we failed to get sub-components, or we failed to extract */
++      /* a CS from a generic CRS, then this is another case we don't */
++      /* handle */
++      if (!pj_sub)
++              lwerror("%s: %s", __func__, 
proj_errno_string(proj_context_errno(NULL)));
++
++      /* If the components are usable, we can extract the CS and return */
++      int pj_type = proj_get_type(pj_sub);
++      if (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || pj_type == 
PJ_TYPE_PROJECTED_CRS)
++      {
++              PJ *pj_2d = proj_crs_get_coordinate_system(NULL, pj_sub);
++              proj_destroy(pj_sub);
++              return pj_2d;
++      }
++
++      /* If the components are *themselves* Bound/Compound, we can recurse */
++      if (pj_type == PJ_TYPE_COMPOUND_CRS || pj_type == PJ_TYPE_BOUND_CRS)
++              return proj_cs_get_simplecs(pj_sub);
++
++      /* This is a case we don't know how to handle */
++      lwerror("%s: un-handled CRS sub-type: %s", __func__, pj_type);
++      return NULL;
++}
++
++static uint8_t
++proj_crs_is_swapped(const PJ *pj_crs)
++{
++      PJ *pj_cs;
++      uint8_t rv = LW_FALSE;
++
++      pj_cs = proj_cs_get_simplecs(pj_crs);
++      if (!pj_cs) {
++              lwerror("%s: proj_cs_get_simplecs returned NULL", __func__);
+       }
+-      if (!pj_cs)
+-              lwerror("%s: proj_crs_get_coordinate_system returned NULL", 
__func__);
+       int axis_count = proj_cs_get_axis_count(NULL, pj_cs);
+       if (axis_count > 0)
+       {
diff -Nru 
postgis-3.1.1+dfsg/debian/patches/0001-Only-do-axis-flips-on-CRS-that-have-a-Lat-as-the-fir.patch
 
postgis-3.1.1+dfsg/debian/patches/0001-Only-do-axis-flips-on-CRS-that-have-a-Lat-as-the-fir.patch
--- 
postgis-3.1.1+dfsg/debian/patches/0001-Only-do-axis-flips-on-CRS-that-have-a-Lat-as-the-fir.patch
   2023-02-16 19:00:56.000000000 +0100
+++ 
postgis-3.1.1+dfsg/debian/patches/0001-Only-do-axis-flips-on-CRS-that-have-a-Lat-as-the-fir.patch
   2023-05-11 09:51:48.000000000 +0200
@@ -7,7 +7,7 @@
 
 --- a/liblwgeom/lwgeom_transform.c
 +++ b/liblwgeom/lwgeom_transform.c
-@@ -245,7 +245,7 @@ proj_crs_is_swapped(const PJ *pj_crs)
+@@ -277,7 +277,7 @@ proj_crs_is_swapped(const PJ *pj_crs)
                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;
@@ -16,7 +16,7 @@
                proj_cs_get_axis_info(NULL,
                                      pj_cs,
                                      0,
-@@ -256,13 +256,10 @@ proj_crs_is_swapped(const PJ *pj_crs)
+@@ -288,13 +288,10 @@ proj_crs_is_swapped(const PJ *pj_crs)
                                      &out_unit_name,
                                      &out_unit_auth_name,
                                      &out_unit_code);
diff -Nru postgis-3.1.1+dfsg/debian/patches/series 
postgis-3.1.1+dfsg/debian/patches/series
--- postgis-3.1.1+dfsg/debian/patches/series    2023-02-16 19:00:56.000000000 
+0100
+++ postgis-3.1.1+dfsg/debian/patches/series    2023-05-11 09:50:45.000000000 
+0200
@@ -1,4 +1,6 @@
 relax-test-timing-constraints.patch
 chaikin
 incorrect-path-for-interpreter.patch
+0001-Handle-more-deeply-nested-CRS-objects-when-extractin.patch
 0001-Only-do-axis-flips-on-CRS-that-have-a-Lat-as-the-fir.patch
+0001-Flip-N-E-systems-to-E-N-and-geodetic-systems-to-Lon-.patch

Reply via email to