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