Skip to content

Commit

Permalink
MySQL: fix/workaround server-side spatial filtering when SRS is geogr…
Browse files Browse the repository at this point in the history
…aphic with MySQL >= 8 (fixes qgis/QGIS#55463)

It seems spatial predicates are not directly usable when using geographic SRS. For some reason

select MBRIntersects(ST_GeomFromText('POLYGON((-90 -90, 90 -90, 90 90, -90 90, -90 -90))', 4326), ST_GeomFromText('POINT(0 0)', 4326));

returns true as expected

But

select MBRIntersects(ST_GeomFromText('POLYGON((-179 -89, 179 -89, 179 89, -179 89, -179 -89))', 4326, 'axis-order=long-lat'), ST_GeomFromText('POINT(0 0)', 4326));

returns false !!!!

And

select MBRIntersects(ST_GeomFromText('POLYGON((-179 -89, 179 -89, 179 89, -179 89, -179 -89))', 32631), ST_GeomFromText('POINT(0 0)', 32631));

returns true as expected

Consequence, we need to force a projected SRS for the arguments of MBRIntersects()
  • Loading branch information
rouault committed Jan 28, 2024
1 parent a79a07c commit bf10950
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 15 deletions.
5 changes: 5 additions & 0 deletions autotest/ogr/ogr_mysql.py
Expand Up @@ -960,6 +960,11 @@ def test_ogr_mysql_longlat(mysql_ds, mysql_is_8_or_later):
pytest.fail("Not found SRID definition with GEOMETORY field.")
mysql_ds.ReleaseResultSet(sql_lyr)

lyr.SetSpatialFilterRect(-181, -91, 181, 91)
lyr.ResetReading()
f = lyr.GetNextFeature()
ogrtest.check_feature_geometry(f, geom)


###############################################################################
# Test writing and reading back geometries
Expand Down
50 changes: 35 additions & 15 deletions ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
Expand Up @@ -32,6 +32,8 @@
#include "cpl_string.h"
#include "ogr_mysql.h"

#include <algorithm>

/************************************************************************/
/* OGRMySQLTableLayer() */
/************************************************************************/
Expand Down Expand Up @@ -467,26 +469,41 @@ void OGRMySQLTableLayer::BuildWhere()
// POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
m_poFilterGeom->getEnvelope(&sEnvelope);

const OGRSpatialReference *l_poSRS = GetSpatialRef();
const bool bIsGeography =
(poDS->GetMajorVersion() >= 8 && !poDS->IsMariaDB() && l_poSRS &&
l_poSRS->IsGeographic());

const double dfMinX = sEnvelope.MinX;
const double dfMinY = sEnvelope.MinY;
const double dfMaxX = sEnvelope.MaxX;
const double dfMaxY = sEnvelope.MaxY;

CPLsnprintf(szEnvelope, sizeof(szEnvelope),
"POLYGON((%.18g %.18g, %.18g %.18g, %.18g %.18g, %.18g "
"%.18g, %.18g %.18g))",
sEnvelope.MinX, sEnvelope.MinY, sEnvelope.MaxX,
sEnvelope.MinY, sEnvelope.MaxX, sEnvelope.MaxY,
sEnvelope.MinX, sEnvelope.MaxY, sEnvelope.MinX,
sEnvelope.MinY);

const char *pszAxisOrder = "";
OGRSpatialReference *l_poSRS = GetSpatialRef();
if (poDS->GetMajorVersion() >= 8 && !poDS->IsMariaDB() && l_poSRS &&
l_poSRS->IsGeographic())
dfMinX, dfMinY, dfMaxX, dfMinY, dfMaxX, dfMaxY, dfMinX,
dfMaxY, dfMinX, dfMinY);

if (bIsGeography)
{
pszAxisOrder = ", 'axis-order=long-lat'";
// Force any projected CRS so that the spatial filter works as
// we expect.
// This is due to the following returning false
// select MBRIntersects(ST_GeomFromText('POLYGON((-179 -89, 179 -89, 179 89, -179 89, -179 -89))', 4326, 'axis-order=long-lat'), ST_GeomFromText('POINT(0 0)', 4326));
snprintf(pszWHERE, nWHERELen,
"WHERE MBRIntersects(ST_GeomFromText('%s', 32631), "
"ST_SRID(`%s`,32631))",
szEnvelope, pszGeomColumn);
}
else
{
snprintf(pszWHERE, nWHERELen,
"WHERE MBRIntersects(%s('%s', %d), `%s`)",
poDS->GetMajorVersion() >= 8 ? "ST_GeomFromText"
: "GeomFromText",
szEnvelope, nSRSId, pszGeomColumn);
}

snprintf(
pszWHERE, nWHERELen, "WHERE MBRIntersects(%s('%s', %d%s), `%s`)",
poDS->GetMajorVersion() >= 8 ? "ST_GeomFromText" : "GeomFromText",
szEnvelope, nSRSId, pszAxisOrder, pszGeomColumn);
}

if (pszQuery != nullptr)
Expand All @@ -497,6 +514,9 @@ void OGRMySQLTableLayer::BuildWhere()
snprintf(pszWHERE + strlen(pszWHERE), nWHERELen - strlen(pszWHERE),
"&& (%s) ", pszQuery);
}

if (pszWHERE[0])
CPLDebug("MYSQL", "Filter: %s", pszWHERE);
}

/************************************************************************/
Expand Down

0 comments on commit bf10950

Please sign in to comment.