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

Поиск
Список
Период
Сортировка
От Matwey V. Kornilov
Тема [PATCH 3/3] Add initial support for spgist quadtree @<(point,circle) operator
Дата
Msg-id 20190201160800.7334-4-matwey.kornilov@gmail.com
обсуждение исходный текст
Ответ на [PATCH 0/3] Introduce spgist quadtree @<(point,circle) operator  ("Matwey V. Kornilov" <matwey.kornilov@gmail.com>)
Список pgsql-hackers
Signed-off-by: Matwey V. Kornilov <matwey.kornilov@gmail.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



В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Matwey V. Kornilov"
Дата:
Сообщение: [PATCH 2/3] Introduce spg_quad_inner_consistent_box_helper() in spgquadtreeproc.c
Следующее
От: Andres Freund
Дата:
Сообщение: fast defaults in heap_getattr vs heap_deform_tuple