[postgis-users] PostGIS transforms st_dwithin to && on geography column without preserving the custom spatial reference system

Michael Loveridge loveridge at ascendingnode.tech
Tue Jun 1 12:09:24 PDT 2021


When I use st_dwithin on a geography column with a GIST index, the 
explain plan shows that the narrowing condition on the index scan is 
changed into a && bounding box condition. With this different condition, 
the result set is missing rows that are included if a st_dwithin is 
performed using a full table scan when there is no index.

The condition in the explain plan without an index is:
st_dwithin(
   geog,
   '010100002010A4000000000000006066400000000000000000'::geography,
   '3'::double precision,
   false
)

But the explain plan indicates that it is changed into the following 
when the column has a GIST index:
geog && _st_expand(
   '010100002010A4000000000000006066400000000000000000'::geography,
   '3'::double precision
)


The geography column has a custom spatial reference system that is not 
being preserved in the transformation into a && condition. The custom 
spatial reference system is a sphere where the radius is such that one 
degree is equal to one meter of great-circle distance. So that a point 
of (0 0) is one distance away from (0 1). But it seems that when using 
st_dwithin, the search is being done in srid 4326 instead of my custom one.

The setup code is below:

-- Insert the custom spatial reference system into the db.
insert into spatial_ref_sys values (42000, 'customsrs', 1,
      'GEOGCS[
        "Normal Sphere (r=57.2957795)",
        DATUM["unknown",
          SPHEROID["Sphere",57.29577951308232087679,0]
        ],
        PRIMEM["Greenwich",0],
        CS[ellipsoidal,2],
        AXIS["latitude",north],
        AXIS["longitude",east],
        UNIT["degree",0.0174532925199433]
      ]', '+proj=longlat +ellps=sphere +R=57.29577951308232087679 
+no_defs');

-- Create a new table with a geography column in the new spatial 
reference system.
CREATE TABLE geographytest(gid serial PRIMARY KEY, geog geography(POINT, 
42000));

-- Insert some data around the dateline
insert into geographytest (gid, geog) values
(1, 'srid=42000;POINT(179 0)'),
(2, 'srid=42000;POINT(178 0)'),
(3, 'srid=42000;POINT(-179 0)'),
(4, 'srid=42000;POINT(-179 90)'),
(5, 'srid=42000;POINT(0 0)');


-- Select all points within a distance of 3 from POINT(179 0).
--   The expected 3 points are returned, with st_distances of 0, 1 and 2.
select
  gid,
  st_distance(
    geog,
    'srid=42000;POINT(179 0)',
    false
  ),
  st_dwithin(
    geog,
    'srid=42000;POINT(179 0)',
    3,
    false
  )
from
  geographytest
where
  st_dwithin(
    geog,
    st_geogfromtext('srid=42000;POINT(179 0)'),
    3,
    false
  );

-- Create a GIST index on our geography column
CREATE INDEX geographytestindex ON geographytest USING gist (geog);
VACUUM analyze geographytest (geog);

-- Now select again using the same query.
--   Now only one result is returned, the row that has POINT(179 0).
--   The explain plan indicates that the index scan is using
--   Index Cond: (geog && 
_st_expand('010100002010A4000000000000006066400000000000000000'::geography, 
'3'::double precision))
--   when performing the select.
select
  gid,
  st_distance(
    geog,
    'srid=42000;POINT(179 0)',
    false
  ),
  st_dwithin(
    geog,
    'srid=42000;POINT(179 0)',
    3,
    false
  )
from
  geographytest
where
  st_dwithin(
    geog,
    st_geogfromtext('srid=42000;POINT(179 0)'),
    3,
    false
  );

Increasing the st_dwithin distance to 230000 instead of 3 returns all 
three of the expected rows, since that is their distance in srid 4326.

How can I get PostGIS to use my custom spatial reference system in the 
query when an index is present on the column?


More information about the postgis-users mailing list