From f0bd7cbd5c398f5a8c89e55a0c26dd6a5ce98218 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 5 Dec 2024 01:13:18 +0100 Subject: [PATCH] ogr2ogr: fix crash with -ct and using Arrow code path (e.g source is GeoPackage) (3.10.0 regression) Fixes #11438 Passing "--config OGR2OGR_USE_ARROW_API=NO" or "-t_srs {srs_def}" can be used as a workaround --- apps/ogr2ogr_lib.cpp | 11 ++++--- autotest/utilities/test_ogr2ogr_lib.py | 40 ++++++++++++++++++++++++++ ogr/ogrgeometryfactory.cpp | 3 +- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/apps/ogr2ogr_lib.cpp b/apps/ogr2ogr_lib.cpp index 91154edcba1d..5006a602b14f 100644 --- a/apps/ogr2ogr_lib.cpp +++ b/apps/ogr2ogr_lib.cpp @@ -4099,12 +4099,11 @@ bool SetupTargetLayer::CanUseWriteArrowBatch( { return false; } - auto poSrcSRS = m_poUserSourceSRS ? m_poUserSourceSRS - : poSrcLayer->GetLayerDefn() - ->GetGeomFieldDefn(0) - ->GetSpatialRef(); - if (!poSrcSRS || - !OGRGeometryFactory::isTransformWithOptionsRegularTransform( + const auto poSrcSRS = m_poUserSourceSRS ? m_poUserSourceSRS + : poSrcLayer->GetLayerDefn() + ->GetGeomFieldDefn(0) + ->GetSpatialRef(); + if (!OGRGeometryFactory::isTransformWithOptionsRegularTransform( poSrcSRS, m_poOutputSRS, nullptr)) { return false; diff --git a/autotest/utilities/test_ogr2ogr_lib.py b/autotest/utilities/test_ogr2ogr_lib.py index 96c9a7e26782..066f8b7a21af 100755 --- a/autotest/utilities/test_ogr2ogr_lib.py +++ b/autotest/utilities/test_ogr2ogr_lib.py @@ -2924,6 +2924,46 @@ def my_handler(errorClass, errno, msg): assert f.GetGeometryRef().GetGeometryCount() == 2 +############################################################################### +# Test -ct in Arrow code path +# Cf https://github.com/OSGeo/gdal/issues/11438 + + +@gdaltest.enable_exceptions() +def test_ogr2ogr_lib_reproject_arrow_optim_ct(tmp_vsimem): + + srcDS = gdal.GetDriverByName("Memory").Create("", 0, 0, 0, gdal.GDT_Unknown) + srs = osr.SpatialReference() + srs.ImportFromEPSG(32632) + srcLayer = srcDS.CreateLayer("test", srs=srs) + f = ogr.Feature(srcLayer.GetLayerDefn()) + f.SetGeometry(ogr.CreateGeometryFromWkt("POINT (1 2)")) + srcLayer.CreateFeature(f) + + got_msg = [] + + def my_handler(errorClass, errno, msg): + got_msg.append(msg) + return + + config_options = {"CPL_DEBUG": "ON", "OGR2OGR_USE_ARROW_API": "YES"} + with gdaltest.error_handler(my_handler), gdaltest.config_options(config_options): + ds = gdal.VectorTranslate( + "", + srcDS, + format="Memory", + reproject=True, + coordinateOperation="+proj=affine +s11=-1", + ) + + assert "OGR2OGR: Using WriteArrowBatch()" in got_msg + + lyr = ds.GetLayer(0) + assert lyr.GetSpatialRef().GetAuthorityCode(None) == "32632" + f = lyr.GetNextFeature() + assert f.GetGeometryRef().ExportToWkt() == "POINT (-1 2)" + + ############################################################################### # Test -explodecollections on empty geometries diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp index f08261bc31c2..944c45efddc6 100644 --- a/ogr/ogrgeometryfactory.cpp +++ b/ogr/ogrgeometryfactory.cpp @@ -3886,7 +3886,8 @@ bool OGRGeometryFactory::isTransformWithOptionsRegularTransform( return false; #ifdef HAVE_GEOS - if (poSourceCRS->IsProjected() && poTargetCRS->IsGeographic() && + if (poSourceCRS && poTargetCRS && poSourceCRS->IsProjected() && + poTargetCRS->IsGeographic() && poTargetCRS->GetAxisMappingStrategy() == OAMS_TRADITIONAL_GIS_ORDER && // check that angular units is degree std::fabs(poTargetCRS->GetAngularUnits(nullptr) -