Skip to content

Commit 6ebf5c2

Browse files
Giuseppe BroccoloVitaly Davydov
Giuseppe Broccolo
authored and
Vitaly Davydov
committed
Add BRIN support for spoint and sbox
Adjust style using pgindent, execute regression test for BRIN code just for PG>9.5
1 parent d0afcdb commit 6ebf5c2

File tree

8 files changed

+1036
-7
lines changed

8 files changed

+1036
-7
lines changed

Diff for: Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ MODULE_big = pg_sphere
1111
OBJS = src/sscan.o src/sparse.o src/sbuffer.o src/vector3d.o src/point.o \
1212
src/euler.o src/circle.o src/line.o src/ellipse.o src/polygon.o \
1313
src/path.o src/box.o src/output.o src/gq_cache.o src/gist.o \
14-
src/key.o src/gnomo.o src/epochprop.o
14+
src/key.o src/gnomo.o src/epochprop.o brin.o
1515

1616
ifneq ($(USE_HEALPIX),0)
1717
OBJS += src/healpix.o src/moc.o src/process_moc.o \
@@ -33,7 +33,7 @@ DATA_built = $(RELEASE_SQL) \
3333
DOCS = README.pg_sphere COPYRIGHT.pg_sphere
3434
REGRESS = init tables points euler circle line ellipse poly path box index \
3535
contains_ops contains_ops_compat bounding_box_gist gnomo epochprop \
36-
contains overlaps
36+
contains overlaps spoint_brin
3737

3838
ifneq ($(USE_HEALPIX),0)
3939
REGRESS += healpix moc mocautocast
@@ -66,7 +66,7 @@ CRUSH_TESTS = init_extended circle_extended
6666
PGS_SQL = pgs_types.sql pgs_point.sql pgs_euler.sql pgs_circle.sql \
6767
pgs_line.sql pgs_ellipse.sql pgs_polygon.sql pgs_path.sql \
6868
pgs_box.sql pgs_contains_ops.sql pgs_contains_ops_compat.sql \
69-
pgs_gist.sql gnomo.sql
69+
pgs_gist.sql gnomo.sql pgs_brin.sql
7070

7171
ifneq ($(USE_HEALPIX),0)
7272
PGS_SQL += healpix.sql

Diff for: README.pg_sphere

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ It provides:
1111

1212
This is an R-Tree implementation using GiST for spherical objects like
1313
spherical points and spherical circles with useful functions and operators.
14+
It also support the Block Range INdexing (BRIN) for large datasets.
1415

1516
NOTICE:
1617
This version will work only with PostgreSQL version 10 and above.

Diff for: brin.c

+348
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
/*
2+
* BRIN SUPPORT for spheric objects:
3+
*
4+
* The stored type is the spherekey, as for GiST support,
5+
* so include some already defined stuffs. We have to define
6+
* then all the cross-type functions needed by the OpFamilies.
7+
*/
8+
9+
#include "brin.h"
10+
#include "gist.h"
11+
#include <fmgr.h>
12+
13+
/*
14+
* Functions needed to build a BRIN index
15+
*/
16+
PG_FUNCTION_INFO_V1(spoint_brin_inclusion_add_value);
17+
PG_FUNCTION_INFO_V1(sbox_brin_inclusion_add_value);
18+
19+
/*
20+
* Functions needed to define supported operators
21+
*/
22+
PG_FUNCTION_INFO_V1(spoint_overlaps_spherekey);
23+
PG_FUNCTION_INFO_V1(spoint_contains_spherekey);
24+
PG_FUNCTION_INFO_V1(spoint_iscontained_spherekey);
25+
PG_FUNCTION_INFO_V1(sbox_overlaps_spherekey);
26+
PG_FUNCTION_INFO_V1(sbox_contains_spherekey);
27+
PG_FUNCTION_INFO_V1(sbox_iscontained_spherekey);
28+
PG_FUNCTION_INFO_V1(spherekey_overlaps_spherekey);
29+
PG_FUNCTION_INFO_V1(spherekey_contains_spherekey);
30+
PG_FUNCTION_INFO_V1(spherekey_iscontained_spherekey);
31+
PG_FUNCTION_INFO_V1(spoint_overlaps_sbox);
32+
PG_FUNCTION_INFO_V1(sbox_iscontained_spoint);
33+
34+
Datum
35+
spoint_brin_inclusion_add_value(PG_FUNCTION_ARGS)
36+
{
37+
BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
38+
SPoint *newval = (SPoint *) DatumGetPointer(PG_GETARG_DATUM(2));
39+
bool isnull = PG_GETARG_BOOL(3);
40+
int32 spointkey[6];
41+
int32 *skey = (int32 *) column->bv_values[INCLUSION_UNION];
42+
43+
/*
44+
* If the new value is null, we record that we saw it if it's the first
45+
* one; otherwise, there's nothing to do.
46+
*/
47+
if (isnull)
48+
{
49+
if (column->bv_hasnulls)
50+
PG_RETURN_BOOL(false);
51+
52+
column->bv_hasnulls = true;
53+
PG_RETURN_BOOL(true);
54+
}
55+
56+
spherepoint_gen_key(&spointkey, newval);
57+
58+
/*
59+
* If spherekey pointer is NULL, we consider the spoint entry as 'empty'.
60+
*
61+
* The OpClass support empty entries: we need to set the "contains empty"
62+
* flag in the element (unless already set).
63+
*/
64+
if (spointkey == NULL)
65+
{
66+
if (!DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]))
67+
{
68+
column->bv_values[INCLUSION_CONTAINS_EMPTY] = BoolGetDatum(true);
69+
PG_RETURN_BOOL(true);
70+
}
71+
72+
PG_RETURN_BOOL(false);
73+
}
74+
75+
/* if the recorded value is null, we just need to store the spherekey */
76+
if (column->bv_allnulls)
77+
{
78+
column->bv_values[INCLUSION_UNION] = datumCopy((Datum) spointkey, false,
79+
(sizeof(int32) * 6));
80+
column->bv_values[INCLUSION_UNMERGEABLE] = BoolGetDatum(false);
81+
column->bv_values[INCLUSION_CONTAINS_EMPTY] = BoolGetDatum(false);
82+
column->bv_allnulls = false;
83+
PG_RETURN_BOOL(true);
84+
}
85+
86+
/*
87+
* Check if the stored spherekey already contains the key of the new value
88+
*/
89+
if (spherekey_interleave(skey, spointkey) == SCKEY_IN)
90+
{
91+
PG_RETURN_BOOL(false);
92+
}
93+
94+
/*
95+
* Otherwise, we need to enlarge it to contains the current spoint
96+
*/
97+
spherekey_union_two(skey, spointkey);
98+
99+
PG_RETURN_BOOL(true);
100+
}
101+
102+
Datum
103+
sbox_brin_inclusion_add_value(PG_FUNCTION_ARGS)
104+
{
105+
BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
106+
SBOX *newval = (SBOX *) DatumGetPointer(PG_GETARG_DATUM(2));
107+
bool isnull = PG_GETARG_BOOL(3);
108+
int32 sboxkey[6];
109+
int32 *skey = (int32 *) column->bv_values[INCLUSION_UNION];
110+
111+
/*
112+
* If the new value is null, we record that we saw it if it's the first
113+
* one; otherwise, there's nothing to do.
114+
*/
115+
if (isnull)
116+
{
117+
if (column->bv_hasnulls)
118+
PG_RETURN_BOOL(false);
119+
120+
column->bv_hasnulls = true;
121+
PG_RETURN_BOOL(true);
122+
}
123+
124+
spherebox_gen_key(&sboxkey, newval);
125+
126+
/*
127+
* If spherekey pointer is NULL, we consider the spoint entry as 'empty'.
128+
*
129+
* The OpClass support empty entries: we need to set the "contains empty"
130+
* flag in the element (unless already set).
131+
*/
132+
if (sboxkey == NULL)
133+
{
134+
if (!DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]))
135+
{
136+
column->bv_values[INCLUSION_CONTAINS_EMPTY] = BoolGetDatum(true);
137+
PG_RETURN_BOOL(true);
138+
}
139+
140+
PG_RETURN_BOOL(false);
141+
}
142+
143+
/* if the recorded value is null, we just need to store the spherekey */
144+
if (column->bv_allnulls)
145+
{
146+
column->bv_values[INCLUSION_UNION] = datumCopy((Datum) sboxkey, false,
147+
(sizeof(int32) * 6));
148+
column->bv_values[INCLUSION_UNMERGEABLE] = BoolGetDatum(false);
149+
column->bv_values[INCLUSION_CONTAINS_EMPTY] = BoolGetDatum(false);
150+
column->bv_allnulls = false;
151+
PG_RETURN_BOOL(true);
152+
}
153+
154+
/*
155+
* Check if the stored spherekey already contains the key of the new value
156+
*/
157+
if (spherekey_interleave(skey, sboxkey) == SCKEY_IN)
158+
{
159+
PG_RETURN_BOOL(false);
160+
}
161+
162+
/*
163+
* Otherwise, we need to enlarge it to contains the current spoint
164+
*/
165+
spherekey_union_two(skey, sboxkey);
166+
167+
PG_RETURN_BOOL(true);
168+
}
169+
170+
/* */
171+
/* Define operators procedures below */
172+
/* */
173+
174+
Datum
175+
spoint_overlaps_spherekey(PG_FUNCTION_ARGS)
176+
{
177+
int32 k1[6];
178+
SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0);
179+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
180+
181+
spherepoint_gen_key(&k1, p1);
182+
if (spherekey_interleave(k1, k2) == SCKEY_OVERLAP)
183+
{
184+
PG_RETURN_BOOL(true);
185+
}
186+
187+
PG_RETURN_BOOL(false);
188+
}
189+
190+
Datum
191+
spoint_contains_spherekey(PG_FUNCTION_ARGS)
192+
{
193+
int32 k1[6];
194+
SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0);
195+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
196+
197+
spherepoint_gen_key(&k1, p1);
198+
if (spherekey_interleave(k1, k2) == SCKEY_IN)
199+
{
200+
PG_RETURN_BOOL(true);
201+
}
202+
203+
PG_RETURN_BOOL(false);
204+
}
205+
206+
Datum
207+
spoint_iscontained_spherekey(PG_FUNCTION_ARGS)
208+
{
209+
int32 k1[6];
210+
SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0);
211+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
212+
213+
spherepoint_gen_key(&k1, p1);
214+
if (spherekey_interleave(k2, k1) == SCKEY_IN)
215+
{
216+
PG_RETURN_BOOL(true);
217+
}
218+
219+
PG_RETURN_BOOL(false);
220+
}
221+
222+
Datum
223+
sbox_overlaps_spherekey(PG_FUNCTION_ARGS)
224+
{
225+
int32 k1[6];
226+
SBOX *p1 = (SBOX *) PG_GETARG_POINTER(0);
227+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
228+
229+
spherebox_gen_key(&k1, p1);
230+
if (spherekey_interleave(k1, k2) == SCKEY_OVERLAP)
231+
{
232+
PG_RETURN_BOOL(true);
233+
}
234+
235+
PG_RETURN_BOOL(false);
236+
}
237+
238+
Datum
239+
sbox_contains_spherekey(PG_FUNCTION_ARGS)
240+
{
241+
int32 k1[6];
242+
SBOX *p1 = (SBOX *) PG_GETARG_POINTER(0);
243+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
244+
245+
spherebox_gen_key(&k1, p1);
246+
if (spherekey_interleave(k1, k2) == SCKEY_IN)
247+
{
248+
PG_RETURN_BOOL(true);
249+
}
250+
251+
PG_RETURN_BOOL(false);
252+
}
253+
254+
Datum
255+
sbox_iscontained_spherekey(PG_FUNCTION_ARGS)
256+
{
257+
int32 k1[6];
258+
SBOX *p1 = (SBOX *) PG_GETARG_POINTER(0);
259+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
260+
261+
spherebox_gen_key(&k1, p1);
262+
if (spherekey_interleave(k2, k1) == SCKEY_IN)
263+
{
264+
PG_RETURN_BOOL(true);
265+
}
266+
267+
PG_RETURN_BOOL(false);
268+
}
269+
270+
Datum
271+
spherekey_overlaps_spherekey(PG_FUNCTION_ARGS)
272+
{
273+
int32 *k1 = (int32 *) PG_GETARG_POINTER(0);
274+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
275+
276+
if (spherekey_interleave(k1, k2) == SCKEY_OVERLAP)
277+
{
278+
PG_RETURN_BOOL(true);
279+
}
280+
281+
PG_RETURN_BOOL(false);
282+
}
283+
284+
Datum
285+
spherekey_contains_spherekey(PG_FUNCTION_ARGS)
286+
{
287+
int32 *k1 = (int32 *) PG_GETARG_POINTER(0);
288+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
289+
290+
if (spherekey_interleave(k1, k2) == SCKEY_IN)
291+
{
292+
PG_RETURN_BOOL(true);
293+
}
294+
295+
PG_RETURN_BOOL(false);
296+
}
297+
298+
Datum
299+
spherekey_iscontained_spherekey(PG_FUNCTION_ARGS)
300+
{
301+
int32 *k1 = (int32 *) PG_GETARG_POINTER(0);
302+
int32 *k2 = (int32 *) PG_GETARG_POINTER(1);
303+
304+
if (spherekey_interleave(k2, k1) == SCKEY_IN)
305+
{
306+
PG_RETURN_BOOL(true);
307+
}
308+
309+
PG_RETURN_BOOL(false);
310+
}
311+
312+
Datum
313+
spoint_overlaps_sbox(PG_FUNCTION_ARGS)
314+
{
315+
int32 k1[6];
316+
SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0);
317+
int32 k2[6];
318+
SBOX *p2 = (SBOX *) PG_GETARG_POINTER(1);
319+
320+
spherepoint_gen_key(&k1, p1);
321+
spherebox_gen_key(&k2, p2);
322+
323+
if (spherekey_interleave(k1, k2) == SCKEY_OVERLAP)
324+
{
325+
PG_RETURN_BOOL(true);
326+
}
327+
328+
PG_RETURN_BOOL(false);
329+
}
330+
331+
Datum
332+
sbox_iscontained_spoint(PG_FUNCTION_ARGS)
333+
{
334+
int32 k1[6];
335+
SBOX *p1 = (SBOX *) PG_GETARG_POINTER(0);
336+
int32 k2[6];
337+
SPoint *p2 = (SPoint *) PG_GETARG_POINTER(1);
338+
339+
spherebox_gen_key(&k1, p1);
340+
spherepoint_gen_key(&k2, p2);
341+
342+
if (spherekey_interleave(k1, k2) == SCKEY_IN)
343+
{
344+
PG_RETURN_BOOL(true);
345+
}
346+
347+
PG_RETURN_BOOL(false);
348+
}

0 commit comments

Comments
 (0)