1-- create table 2CREATE TABLE knn_recheck_geom(gid serial primary key, geom geometry); 3INSERT INTO knn_recheck_geom(gid,geom) 4SELECT ROW_NUMBER() OVER(ORDER BY x,y) AS gid, ST_Point(x*0.777,y*0.887) As geom 5FROM generate_series(-100,1000, 7) AS x CROSS JOIN generate_series(-300,1000,9) As y; 6 7INSERT INTO knn_recheck_geom(gid, geom) 8SELECT 500000 + i, ST_Translate('LINESTRING(-100 300, 500 700, 400 123, 500 10000, 1 1)'::geometry, i*2000,0) 9FROM generate_series(0,10) i; 10 11INSERT INTO knn_recheck_geom(gid, geom) 12SELECT 500100 + i, ST_Translate('POLYGON((100 800, 100 700, 400 123, 405 124, 100 800))'::geometry,0,i*2000) 13FROM generate_series(0,3) i; 14 15 16INSERT INTO knn_recheck_geom(gid,geom) 17SELECT 600000 + ROW_NUMBER() OVER(ORDER BY gid) AS gid, ST_Translate(ST_Buffer(geom,8,15 ),100,300) As geom 18FROM knn_recheck_geom 19WHERE gid IN(1000, 10000, 2000,3000); 20 21 22-- without index order should match st_distance order -- 23-- point check 24 25SELECT '#1' As t, gid, ST_Distance( 'POINT(-305 998.5)'::geometry, geom)::numeric(10,2) 26FROM knn_recheck_geom 27ORDER BY 'POINT(-305 998.5)'::geometry <-> geom LIMIT 5; 28 29-- linestring check 30SELECT '#2' As t, gid, ST_Distance( 'MULTILINESTRING((-95 -300, 100 200, 100 323),(-50 2000, 30 6000))'::geometry, geom)::numeric(12,4) 31FROM knn_recheck_geom 32ORDER BY 'MULTILINESTRING((-95 -300, 100 200, 100 323),(-50 2000, 30 6000))'::geometry <-> geom LIMIT 5; 33 34-- lateral check before index 35SELECT '#3' As t, a.gid, b.gid As match, ST_Distance(a.geom, b.geom)::numeric(15,4) As true_rn, b.knn_dist::numeric(15,4) 36FROM knn_recheck_geom As a 37 LEFT JOIN 38 LATERAL ( SELECT gid, geom, a.geom <-> g.geom As knn_dist 39 FROM knn_recheck_geom As g WHERE a.gid <> g.gid ORDER BY a.geom <-> g.geom LIMIT 5) As b ON true 40 WHERE a.gid IN(1,500101) 41ORDER BY a.gid, true_rn, b.gid; 42 43-- create index and repeat 44CREATE INDEX idx_knn_recheck_geom_gist ON knn_recheck_geom USING gist(geom); 45vacuum analyze knn_recheck_geom; 46 47set enable_seqscan = false; 48SELECT '#1' As t, gid, ST_Distance( 'POINT(-305 998.5)'::geometry, geom)::numeric(10,2) 49FROM knn_recheck_geom 50ORDER BY 'POINT(-305 998.5)'::geometry <-> geom LIMIT 5; 51 52-- linestring check 53SELECT '#2' As t, gid, ST_Distance( 'MULTILINESTRING((-95 -300, 100 200, 100 323),(-50 2000, 30 6000))'::geometry, geom)::numeric(12,4) 54FROM knn_recheck_geom 55ORDER BY 'MULTILINESTRING((-95 -300, 100 200, 100 323),(-50 2000, 30 6000))'::geometry <-> geom LIMIT 5; 56 57-- lateral check before index 58SELECT '#3' As t, a.gid, b.gid As match, ST_Distance(a.geom, b.geom)::numeric(15,4) As true_rn, b.knn_dist::numeric(15,4) 59FROM knn_recheck_geom As a 60 LEFT JOIN 61 LATERAL ( SELECT gid, geom, a.geom <-> g.geom As knn_dist 62 FROM knn_recheck_geom As g WHERE a.gid <> g.gid ORDER BY a.geom <-> g.geom LIMIT 5) As b ON true 63 WHERE a.gid IN(1,500101) 64ORDER BY a.gid, true_rn, b.gid; 65 66DROP TABLE knn_recheck_geom; 67 68-- geography tests 69DELETE FROM spatial_ref_sys where srid = 4326; 70INSERT INTO "spatial_ref_sys" ("srid","auth_name","auth_srid","proj4text") 71 VALUES (4326,'EPSG',4326,'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '); 72-- create table 73CREATE TABLE knn_recheck_geog(gid serial primary key, geog geography); 74INSERT INTO knn_recheck_geog(gid,geog) 75SELECT ROW_NUMBER() OVER(ORDER BY x,y) AS gid, ST_Point(x*1.11,y*0.95)::geography As geog 76FROM generate_series(-100,100, 1) AS x CROSS JOIN generate_series(-90,90,1) As y; 77 78INSERT INTO knn_recheck_geog(gid, geog) 79SELECT 500000, 'LINESTRING(-95 -10, -93 -10.5, -90 -10.6, -95 -10.5, -95 -10)'::geography; 80 81INSERT INTO knn_recheck_geog(gid, geog) 82SELECT 500001, 'POLYGON((-95 10, -95.6 10.5, -95.9 10.75, -95 10))'::geography; 83 84INSERT INTO knn_recheck_geog(gid,geog) 85SELECT 600000 + ROW_NUMBER() OVER(ORDER BY gid) AS gid, ST_Buffer(geog,1000) As geog 86FROM knn_recheck_geog 87WHERE gid IN(1000, 10000, 2000, 2614, 40000); 88 89 90SELECT '#1g' As t, gid, ST_Distance( 'POINT(-95 -10)'::geography, geog, false)::numeric(12,4) , 91 ('POINT(-95 -10)'::geography <-> geog )::numeric(12,4) 92FROM knn_recheck_geog 93ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5; 94 95SELECT '#2g' As t, gid, ST_Distance( 'LINESTRING(75 10, 75 12, 80 20)'::geography, geog, false)::numeric(12,4), 96 ('LINESTRING(75 10, 75 12, 80 20)'::geography <-> geog)::numeric(12,4) As knn_dist 97FROM knn_recheck_geog 98ORDER BY 'LINESTRING(75 10, 75 12, 80 20)'::geography <-> geog LIMIT 5; 99 100-- lateral check before index 101SELECT '#3g' As t, a.gid, ARRAY(SELECT gid 102 FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY ST_Distance(a.geog, g.geog, false) LIMIT 5) = ARRAY(SELECT gid 103 FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree 104FROM knn_recheck_geog As a 105 WHERE a.gid IN(500000,500010,1000) 106ORDER BY a.gid; 107 108 109-- create index and repeat 110CREATE INDEX idx_knn_recheck_geog_gist ON knn_recheck_geog USING gist(geog); 111vacuum analyze knn_recheck_geog; 112set enable_seqscan = false; 113 114SELECT '#1g' As t, gid, ST_Distance( 'POINT(-95 -10)'::geography, geog, false)::numeric(12,4) , 115 ('POINT(-95 -10)'::geography <-> geog )::numeric(12,4) 116FROM knn_recheck_geog 117ORDER BY 'POINT(-95 -10)'::geography <-> geog LIMIT 5; 118 119SELECT '#2g' As t, gid, ST_Distance( 'LINESTRING(75 10, 75 12, 80 20)'::geography, geog, false)::numeric(12,4), 120 ('LINESTRING(75 10, 75 12, 80 20)'::geography <-> geog)::numeric(12,4) As knn_dist 121FROM knn_recheck_geog 122ORDER BY 'LINESTRING(75 10, 75 12, 80 20)'::geography <-> geog LIMIT 5; 123 124SELECT '#3g' As t, a.gid, ARRAY(SELECT g.gid 125 FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY ST_Distance(a.geog, g.geog, false) LIMIT 5) = ARRAY(SELECT gid 126 FROM knn_recheck_geog As g WHERE a.gid <> g.gid ORDER BY a.geog <-> g.geog LIMIT 5) As dist_order_agree 127FROM knn_recheck_geog As a 128 WHERE a.gid IN(500000,500010,1000) 129ORDER BY a.gid; 130 131DROP TABLE knn_recheck_geog; 132 133-- 134-- Delete inserted spatial data 135-- 136DELETE FROM spatial_ref_sys WHERE srid = 4326; 137 138--now the nd operator tests 139-- create table and load 140CREATE TABLE knn_recheck_geom_nd(gid serial primary key, geom geometry); 141INSERT INTO knn_recheck_geom_nd(gid,geom) 142SELECT ROW_NUMBER() OVER(ORDER BY x,y,z) AS gid, ST_MakePoint(x*0.777,y*0.887,z*1.05) As geom 143FROM generate_series(-100,1000, 7) AS x , 144 generate_series(-300,1000,9) As y, 145 generate_series(1005,10000,5555) As z ; 146 147 -- 3d lines 148INSERT INTO knn_recheck_geom_nd(gid, geom) 149SELECT 500000 + i, ST_Translate('LINESTRING(-100 300 500, 500 700 600, 400 123 0, 500 10000 -1234, 1 1 5000)'::geometry, i*2000,0) 150FROM generate_series(0,10) i; 151 152 153-- 3d polygons 154INSERT INTO knn_recheck_geom_nd(gid, geom) 155SELECT 500100 + i, ST_Translate('POLYGON((100 800 5678, 100 700 5678, 400 123 5678, 405 124 5678, 100 800 5678))'::geometry,0,i*2000) 156FROM generate_series(0,3) i; 157 158-- polyhedral surface -- 159INSERT INTO knn_recheck_geom_nd(gid,geom) 160SELECT 600000 + row_number() over(), ST_Translate(the_geom,100, 450,1000) As the_geom 161 FROM (VALUES ( ST_GeomFromText( 162'PolyhedralSurface( 163((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), 164((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), 165((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) 166)') ) , 167( ST_GeomFromText( 168'PolyhedralSurface( 169((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), 170((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)) )') ) ) 171As foo(the_geom) ; 172 173-- without index order should match st_3ddistance order -- 174-- point check 175SELECT '#1nd-3' As t, gid, ST_3DDistance( 'POINT(-305 998.5 1000)'::geometry, geom)::numeric(12,4) As dist3d, 176('POINT(-305 998.5 1000)'::geometry <<->> geom)::numeric(12,4) As dist_knn 177FROM knn_recheck_geom_nd 178ORDER BY 'POINT(-305 998.5 1000)'::geometry <<->> geom LIMIT 5; 179 180-- linestring check 181SELECT '#2nd-3' As t, gid, ST_3DDistance( 'MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry::geometry, geom)::numeric(12,4), 182 ('MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry <<->> geom)::numeric(12,4) As knn_dist 183FROM knn_recheck_geom_nd 184ORDER BY 'MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry <<->> geom LIMIT 5; 185 186-- lateral test 187SELECT '#3nd-3' As t, a.gid, b.gid As match, ST_3DDistance(a.geom, b.geom)::numeric(15,4) As true_rn, b.knn_dist::numeric(15,4) 188FROM knn_recheck_geom_nd As a 189 LEFT JOIN 190 LATERAL ( SELECT gid, geom, a.geom <<->> g.geom As knn_dist 191 FROM knn_recheck_geom_nd As g WHERE a.gid <> g.gid ORDER BY a.geom <<->> g.geom LIMIT 5) As b ON true 192 WHERE a.gid IN(1,600001) 193ORDER BY a.gid, true_rn, b.gid; 194 195-- create index and repeat 196CREATE INDEX idx_knn_recheck_geom_nd_gist ON knn_recheck_geom_nd USING gist(geom gist_geometry_ops_nd); 197vacuum analyze knn_recheck_geom_nd; 198set enable_seqscan = false; 199-- point check 200SELECT '#1nd-3' As t, gid, ST_3DDistance( 'POINT(-305 998.5 1000)'::geometry, geom)::numeric(12,4) As dist3d, 201('POINT(-305 998.5 1000)'::geometry <<->> geom)::numeric(12,4) As dist_knn 202FROM knn_recheck_geom_nd 203ORDER BY 'POINT(-305 998.5 1000)'::geometry <<->> geom LIMIT 5; 204 205-- linestring check 206SELECT '#2nd-3' As t, gid, ST_3DDistance( 'MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry::geometry, geom)::numeric(12,4), 207 ('MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry <<->> geom)::numeric(12,4) As knn_dist 208FROM knn_recheck_geom_nd 209ORDER BY 'MULTILINESTRING((-95 -300 5000, 105 451 1000, 100 323 200),(-50 2000 456, 30 6000 789))'::geometry <<->> geom LIMIT 5; 210 211-- lateral test 212SELECT '#3nd-3' As t, a.gid, b.gid As match, ST_3DDistance(a.geom, b.geom)::numeric(15,4) As true_rn, b.knn_dist::numeric(15,4) 213FROM knn_recheck_geom_nd As a 214 LEFT JOIN 215 LATERAL ( SELECT gid, geom, a.geom <<->> g.geom As knn_dist 216 FROM knn_recheck_geom_nd As g WHERE a.gid <> g.gid ORDER BY a.geom <<->> g.geom LIMIT 5) As b ON true 217 WHERE a.gid IN(1,600001) 218ORDER BY a.gid, true_rn, b.gid; 219 220 221DROP TABLE knn_recheck_geom_nd; 222 223-- #3573 224SELECT '#3573', 'POINT M (0 0 13)'::geometry <<->> 'LINESTRING M (0 0 5, 0 1 6)'::geometry; 225 226-- #3418 227CREATE TABLE test_wo (geo geometry); 228INSERT INTO test_wo VALUES 229 ('0101000020E61000007D91D0967329E4BF6631B1F9B8D64A40'::geometry), 230 ('0101000020E6100000E2AFC91AF510C1BFCDCCCCCCCCAC4A40'::geometry); 231CREATE INDEX ON TEST_WO USING GIST (GEO); 232analyze test_wo; 233SET enable_seqscan = false; 234SELECT '#3418' As ticket, '0101000020E610000092054CE0D6DDE5BFCDCCCCCCCCAC4A40'::geometry <-> geo, ST_Distance('0101000020E610000092054CE0D6DDE5BFCDCCCCCCCCAC4A40'::geometry, geo) 235FROM test_wo ORDER BY geo <-> 236('0101000020E610000092054CE0D6DDE5BFCDCCCCCCCCAC4A40'::geometry); 237DROP TABLE test_wo; 238set enable_seqscan to default; 239