I'm implementing the recheck functionality for PostGIS so we can
support it when 9.5 comes out, and came across this fun little
crasher.
This works:
select id, name from geonames order by geom <->
'SRID=4326;POINT(-75.6163 39.746)'::geometry limit 10;
This crashes (just reversing the argument order to the <-> operator):
select id, name from geonames order by 'SRID=4326;POINT(-75.6163
39.746)'::geometry <-> geom limit 10;
The stack trace on crash looks like this:
* thread #1: tid = 0x8d2bb, 0x0000000100455247
postgres`create_indexscan_plan(root=0x00007fbf8d005c80,
best_path=0x00007fbf8b823600, tlist=0x00007fbf8d0088d0,
scan_clauses=0x0000000000000000, indexonly='\0') + 1063 at
createplan.c:1354, queue = 'com.apple.main-thread', stop reason =
EXC_BAD_ACCESS (code=1, address=0x24)
* frame #0: 0x0000000100455247
postgres`create_indexscan_plan(root=0x00007fbf8d005c80,
best_path=0x00007fbf8b823600, tlist=0x00007fbf8d0088d0,
scan_clauses=0x0000000000000000, indexonly='\0') + 1063 at
createplan.c:1354
frame #1: 0x00000001004518c9
postgres`create_scan_plan(root=0x00007fbf8d005c80,
best_path=0x00007fbf8b823600) + 377 at createplan.c:360
frame #2: 0x000000010044e749
postgres`create_plan_recurse(root=0x00007fbf8d005c80,
best_path=0x00007fbf8b823600) + 73 at createplan.c:248
frame #3: 0x000000010044e691
postgres`create_plan(root=0x00007fbf8d005c80,
best_path=0x00007fbf8b823600) + 113 at createplan.c:209
frame #4: 0x0000000100460770
postgres`grouping_planner(root=0x00007fbf8d005c80,
tuple_fraction=0.0000048008487900660838) + 4560 at planner.c:1736
frame #5: 0x000000010045e1dd
postgres`subquery_planner(glob=0x00007fbf8b823950,
parse=0x00007fbf8b823060, parent_root=0x0000000000000000,
hasRecursion='\0', tuple_fraction=0, subroot=0x00007fff5faf7028) +
2461 at planner.c:619
frame #6: 0x000000010045d4a2
postgres`standard_planner(parse=0x00007fbf8b823060, cursorOptions=0,
boundParams=0x0000000000000000) + 450 at planner.c:229
frame #7: 0x000000010045d2d1
postgres`planner(parse=0x00007fbf8b823060, cursorOptions=0,
boundParams=0x0000000000000000) + 81 at planner.c:157
frame #8: 0x000000010054ab6c
postgres`pg_plan_query(querytree=0x00007fbf8b823060, cursorOptions=0,
boundParams=0x0000000000000000) + 140 at postgres.c:809
frame #9: 0x000000010054ac43
postgres`pg_plan_queries(querytrees=0x00007fbf8d006230,
cursorOptions=0, boundParams=0x0000000000000000) + 115 at
postgres.c:868
frame #10: 0x000000010054d920
postgres`exec_simple_query(query_string=0x00007fbf8b821a38) + 800 at
postgres.c:1033
frame #11: 0x000000010054cda2 postgres`PostgresMain(argc=1,
argv=0x00007fbf8b8066d0, dbname=0x00007fbf8b806538,
username=0x00007fbf8b806518) + 2546 at postgres.c:4025
frame #12: 0x00000001004b17fe
postgres`BackendRun(port=0x00007fbf8b4079d0) + 686 at
postmaster.c:4162
frame #13: 0x00000001004b0d90
postgres`BackendStartup(port=0x00007fbf8b4079d0) + 384 at
postmaster.c:3838
frame #14: 0x00000001004ad497 postgres`ServerLoop + 663 at postmaster.c:1594
frame #15: 0x00000001004aab9c postgres`PostmasterMain(argc=3,
argv=0x00007fbf8b407760) + 5644 at postmaster.c:1241
frame #16: 0x00000001003e649d postgres`main(argc=3,
argv=0x00007fbf8b407760) + 749 at main.c:221
frame #17: 0x00007fff8ca915fd libdyld.dylib`start + 1
And my SQL declarations look like this:
#if POSTGIS_PGSQL_VERSION >= 95
-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION geography_knn_distance(geography, geography) RETURNS float8 AS
'MODULE_PATHNAME','geography_distance'LANGUAGE 'c' IMMUTABLE STRICT COST 100;
-- Availability: 2.2.0
CREATE OPERATOR <-> ( LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_knn_distance, COMMUTATOR =
'<->'
);
-- Availability: 2.2.0
CREATE OR REPLACE FUNCTION geography_gist_distance(internal, geography, int4)
RETURNS float8
AS 'MODULE_PATHNAME' ,'gserialized_gist_distance'
LANGUAGE 'c';
#endif
-- Availability: 1.5.0
CREATE OPERATOR CLASS gist_geography_ops
DEFAULT FOR TYPE geography USING GIST AS
STORAGE gidx,
OPERATOR 3 && ,
-- OPERATOR 6 ~= ,
-- OPERATOR 7 ~ ,
-- OPERATOR 8 @ ,
#if POSTGIS_PGSQL_VERSION >= 95
-- Availability: 2.2.0
OPERATOR 13 <-> FOR ORDER BY pg_catalog.float_ops,
FUNCTION 8 geography_gist_distance (internal, geography, int4),
#endif
FUNCTION 1 geography_gist_consistent (internal, geography, int4),
FUNCTION 2 geography_gist_union (bytea, internal),
FUNCTION 3 geography_gist_compress (internal),
FUNCTION 4 geography_gist_decompress (internal),
FUNCTION 5 geography_gist_penalty (internal, internal, internal),
FUNCTION 6 geography_gist_picksplit (internal, internal),
FUNCTION 7 geography_gist_same (box2d, box2d, internal);