[PATCH 3/3] Add initial support for spgist quadtree @<(point,circle) operator

From: "Matwey V(dot) Kornilov" <matwey(dot)kornilov(at)gmail(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Cc: "Matwey V(dot) Kornilov" <matwey(dot)kornilov(at)gmail(dot)com>, akorotkov(at)postgresql(dot)org, teodor(at)postgrespro(dot)ru
Subject: [PATCH 3/3] Add initial support for spgist quadtree @<(point,circle) operator
Date: 2019-02-01 16:08:00
Message-ID: 20190201160800.7334-4-matwey.kornilov@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Signed-off-by: Matwey V. Kornilov <matwey(dot)kornilov(at)gmail(dot)com>
---
src/backend/access/spgist/spgquadtreeproc.c | 65 ++++++++++++++++---
src/include/catalog/pg_amop.dat | 3 +
src/test/regress/expected/create_index.out | 96 +++++++++++++++++++++++++++++
src/test/regress/sql/create_index.sql | 32 ++++++++++
4 files changed, 189 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c
index 4904dbbe7b..034e706812 100644
--- a/src/backend/access/spgist/spgquadtreeproc.c
+++ b/src/backend/access/spgist/spgquadtreeproc.c
@@ -142,6 +142,36 @@ static int spg_quad_inner_consistent_box_helper(ScanKey sk, Point *centroid)
return r;
}

+static int spg_quad_inner_consistent_circle_helper(ScanKey sk, Point *centroid)
+{
+ CIRCLE *circleQuery = DatumGetCircleP(sk->sk_argument);
+ int r = 0;
+
+ const Point cp = {
+ .x = centroid->x - circleQuery->center.x,
+ .y = centroid->y - circleQuery->center.y
+ };
+ const Point cp2 = {
+ .x = cp.x * cp.x,
+ .y = cp.y * cp.y
+ };
+ const float8 R2 = circleQuery->radius * circleQuery->radius;
+
+ const float8 x_p0 = (0. > cp.x ? 0. : cp2.x);
+ const float8 y_p0 = (0. > cp.y ? 0. : cp2.y);
+ const float8 x_n0 = (0. < cp.x ? 0. : cp2.x);
+ const float8 y_n0 = (0. < cp.y ? 0. : cp2.y);
+
+ const float8 d[4] = {x_p0 + y_p0, x_p0 + y_n0, x_n0 + y_n0, x_n0 + y_p0};
+
+ for (int i = 0; i < 4; i++) {
+ if (d[i] <= R2)
+ r |= (1 << (i + 1));
+ }
+
+ return r;
+}
+
Datum
spg_quad_choose(PG_FUNCTION_ARGS)
{
@@ -355,7 +385,18 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
which &= (1 << 1) | (1 << 4);
break;
case RTContainedByStrategyNumber:
- which &= spg_quad_inner_consistent_box_helper(sk, centroid);
+
+ switch (sk->sk_subtype) {
+ case BOXOID:
+ which &= spg_quad_inner_consistent_box_helper(sk, centroid);
+ break;
+ case CIRCLEOID:
+ which &= spg_quad_inner_consistent_circle_helper(sk, centroid);
+ break;
+ default:
+ elog(ERROR, "unrecognized right type OID: %d", sk->sk_subtype);
+ break;
+ }
break;
default:
elog(ERROR, "unrecognized strategy number: %d", sk->sk_strategy);
@@ -442,12 +483,22 @@ spg_quad_leaf_consistent(PG_FUNCTION_ARGS)
break;
case RTContainedByStrategyNumber:

- /*
- * For this operator, the query is a box not a point. We
- * cheat to the extent of assuming that DatumGetPointP won't
- * do anything that would be bad for a pointer-to-box.
- */
- res = SPTEST(box_contain_pt, query, datum);
+ switch (sk->sk_subtype) {
+ case BOXOID:
+ /*
+ * For this operator, the query is a box not a point. We
+ * cheat to the extent of assuming that DatumGetPointP won't
+ * do anything that would be bad for a pointer-to-box.
+ */
+ res = SPTEST(box_contain_pt, query, datum);
+ break;
+ case CIRCLEOID:
+ res = SPTEST(circle_contain_pt, query, datum);
+ break;
+ default:
+ elog(ERROR, "unrecognized right type OID: %d", sk->sk_subtype);
+ break;
+ }
break;
default:
elog(ERROR, "unrecognized strategy number: %d", sk->sk_strategy);
diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat
index 0ab95d8a24..fb7157aa44 100644
--- a/src/include/catalog/pg_amop.dat
+++ b/src/include/catalog/pg_amop.dat
@@ -1373,6 +1373,9 @@
amoprighttype => 'box', amopstrategy => '8', amopopr => '<@(point,box)',
amopmethod => 'spgist' },
{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'circle', amopstrategy => '8', amopopr => '<@(point,circle)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
amopopr => '<->(point,point)', amopmethod => 'spgist',
amopsortfamily => 'btree/float_ops' },
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 46deb55c67..4ff8745792 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -271,6 +271,102 @@ SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p;
1057
(1 row)

+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,399),1.41>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,399),1.42>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,401),1.41>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,401),1.42>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,399),1.41>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,399),1.42>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,401),1.41>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,401),1.42>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,399),0.99>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,399),1.01>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,401),0.99>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,401),1.01>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,400),0.99>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,400),1.01>';
+ count
+-------
+ 1000
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,400),0.99>';
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,400),1.01>';
+ count
+-------
+ 1000
+(1 row)
+
SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)';
count
-------
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 59da6b6592..90d0f54792 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -188,6 +188,38 @@ SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)';

SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p;

+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,399),1.41>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,399),1.42>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,401),1.41>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,401),1.42>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,399),1.41>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,399),1.42>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,401),1.41>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,401),1.42>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,399),0.99>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,399),1.01>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,401),0.99>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(333,401),1.01>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,400),0.99>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(332,400),1.01>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,400),0.99>';
+
+SELECT count(*) FROM quad_point_tbl WHERE p <@ circle '<(334,400),1.01>';
+
SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)';

SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)';
--
2.13.7

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2019-02-01 16:24:04 fast defaults in heap_getattr vs heap_deform_tuple
Previous Message Matwey V. Kornilov 2019-02-01 16:07:59 [PATCH 2/3] Introduce spg_quad_inner_consistent_box_helper() in spgquadtreeproc.c