Skip to content

Commit

Permalink
Merge pull request #102 from cybertec-postgresql/hash-opclass
Browse files Browse the repository at this point in the history
Hash opclass for spoint
  • Loading branch information
vitcpp authored Nov 7, 2023
2 parents b4a6fe4 + 035cfe9 commit 339ed93
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ CRUSH_TESTS = init_extended circle_extended
PGS_SQL = pgs_types.sql pgs_point.sql pgs_euler.sql pgs_circle.sql \
pgs_line.sql pgs_ellipse.sql pgs_polygon.sql pgs_path.sql \
pgs_box.sql pgs_contains_ops.sql pgs_contains_ops_compat.sql \
pgs_gist.sql gnomo.sql pgs_brin.sql pgs_circle_sel.sql
pgs_gist.sql gnomo.sql pgs_brin.sql pgs_circle_sel.sql pgs_hash.sql

ifneq ($(USE_HEALPIX),0)
TESTS += healpix moc moc1 moc100 mocautocast
Expand Down Expand Up @@ -199,7 +199,7 @@ ifeq ($(has_index_options),y)
pg_sphere--1.3.1--1.3.2.sql: pgs_moc_options.sql.in
endif
endif
pg_sphere--1.3.1--1.3.2.sql: pgs_circle_sel.sql.in
pg_sphere--1.3.1--1.3.2.sql: pgs_circle_sel.sql.in pgs_hash.sql.in
cat upgrade_scripts/$@.in $^ > $@

# end of local stuff
Expand Down
25 changes: 25 additions & 0 deletions doc/indices.sgm
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,29 @@

</sect1>

<sect1 id="ind.hash">
<title>
Hash index
</title>
<para>
Values of type <type>spoint</type> can be indexed using a
<literal>HASH</literal> index, supporting the
<link linkend="op.equal"><literal>=</literal></link> operator.
The <literal>spoint_hash_ops</literal> operator class also enables
<literal>DISTINCT</literal> queries on <type>spoint</type>.
</para>
<example>
<title>Hash index of spoints</title>
<programlisting>
<![CDATA[CREATE TABLE sky (]]>
<![CDATA[ star spoint]]>
<![CDATA[);]]>
<![CDATA[CREATE INDEX ON sky USING HASH (star);]]>
<![CDATA[]]>
<![CDATA[SELECT DISTINCT star FROM sky;]]>
</programlisting>
</example>

</sect1>

</chapter>
36 changes: 36 additions & 0 deletions expected/index.out
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,39 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM spheretmp1b WHERE p = spoint '(3.09 , 1
4
(1 row)

-- test hash opclass
CREATE TABLE spheretmp1c AS TABLE spheretmp1;
SELECT p FROM spheretmp1c WHERE p <@ scircle '<(1,1),0.2>' ORDER BY p::text;
p
---------------
(0.67 , 0.97)
(0.67 , 0.97)
(0.67 , 0.97)
(0.67 , 0.97)
(1.07 , 1.09)
(1.07 , 1.09)
(1.07 , 1.09)
(1.07 , 1.09)
(1.24 , 0.95)
(1.24 , 0.95)
(1.24 , 0.95)
(1.24 , 0.95)
(12 rows)

WITH points AS (SELECT DISTINCT p FROM spheretmp1c WHERE p <@ scircle '<(1,1),0.2>')
SELECT p FROM points ORDER BY p::text;
p
---------------
(0.67 , 0.97)
(1.07 , 1.09)
(1.24 , 0.95)
(3 rows)

CREATE INDEX spheretmp1c_hash_idx ON spheretmp1c USING hash(p);
EXPLAIN (COSTS OFF) SELECT * FROM spheretmp1c WHERE p = '(0.67 , 0.97)';
QUERY PLAN
------------------------------------------------------
Index Scan using spheretmp1c_hash_idx on spheretmp1c
Index Cond: (p = '(0.67 , 0.97)'::spoint)
(2 rows)

19 changes: 19 additions & 0 deletions pgs_hash.sql.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CREATE FUNCTION spoint_hash32 (spoint)
RETURNS int
IMMUTABLE STRICT
PARALLEL SAFE
LANGUAGE C
AS 'MODULE_PATHNAME', 'spherepoint_hash32';

UPDATE pg_operator
SET oprcanhash = true
WHERE oprname = '=' AND
oprleft = 'spoint'::regtype AND oprright = 'spoint'::regtype;

/* PG17: ALTER OPERATOR = (spoint, spoint) SET (HASHES); */

CREATE OPERATOR CLASS spoint_hash_ops
DEFAULT FOR TYPE spoint USING hash
AS
OPERATOR 1 = (spoint, spoint),
FUNCTION 1 spoint_hash32(spoint);
11 changes: 11 additions & 0 deletions sql/index.sql
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM spheretmp1b WHERE p <@ scircle '<(1,1),
SELECT count(*) FROM spheretmp1b WHERE p <@ scircle '<(1,1),0.3>';
EXPLAIN (COSTS OFF) SELECT count(*) FROM spheretmp1b WHERE p = spoint '(3.09 , 1.25)';
SELECT count(*) FROM spheretmp1b WHERE p = spoint '(3.09 , 1.25)';

-- test hash opclass

CREATE TABLE spheretmp1c AS TABLE spheretmp1;

SELECT p FROM spheretmp1c WHERE p <@ scircle '<(1,1),0.2>' ORDER BY p::text;
WITH points AS (SELECT DISTINCT p FROM spheretmp1c WHERE p <@ scircle '<(1,1),0.2>')
SELECT p FROM points ORDER BY p::text;

CREATE INDEX spheretmp1c_hash_idx ON spheretmp1c USING hash(p);
EXPLAIN (COSTS OFF) SELECT * FROM spheretmp1c WHERE p = '(0.67 , 0.97)';
11 changes: 11 additions & 0 deletions src/point.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ PG_FUNCTION_INFO_V1(spherepoint_y);
PG_FUNCTION_INFO_V1(spherepoint_z);
PG_FUNCTION_INFO_V1(spherepoint_xyz);
PG_FUNCTION_INFO_V1(spherepoint_equal);
PG_FUNCTION_INFO_V1(spherepoint_hash32);

static Oid point_id = InvalidOid;

Expand Down Expand Up @@ -309,3 +310,13 @@ spherepoint_equal(PG_FUNCTION_ARGS)

PG_RETURN_BOOL(spoint_eq(p1, p2));
}

Datum
spherepoint_hash32(PG_FUNCTION_ARGS)
{
SPoint *p1 = (SPoint *) PG_GETARG_POINTER(0);
Datum h1 = DirectFunctionCall1(hashfloat8, p1->lat);
Datum h2 = DirectFunctionCall1(hashfloat8, p1->lng);

PG_RETURN_INT32(DatumGetInt32(h1) ^ DatumGetInt32(h2));
}
5 changes: 5 additions & 0 deletions src/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,9 @@ Datum spherepoint_xyz(PG_FUNCTION_ARGS);
*/
Datum spherepoint_equal(PG_FUNCTION_ARGS);

/*
* Compute a 32-bit hash value of a point.
*/
Datum spherepoint_hash32(PG_FUNCTION_ARGS);

#endif

0 comments on commit 339ed93

Please sign in to comment.