[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