mirror of https://github.com/postgres/postgres
Currently, KNN searches were supported only by GiST. SP-GiST also capable to support them. This commit implements that support. SP-GiST scan stack is replaced with queue, which serves as stack if no ordering is specified. KNN support is provided for three SP-GIST opclasses: quad_point_ops, kd_point_ops and poly_ops (catversion is bumped). Some common parts between GiST and SP-GiST KNNs are extracted into separate functions. Discussion: https://postgr.es/m/570825e8-47d0-4732-2bf6-88d67d2d51c8%40postgrespro.ru Author: Nikita Glukhov, Alexander Korotkov based on GSoC work by Vlad Sterzhanov Review: Andrey Borodin, Alexander Korotkovpull/34/head
parent
d0cfc3d6a4
commit
2a6368343f
@ -0,0 +1,88 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* spgproc.c |
||||
* Common supporting procedures for SP-GiST opclasses. |
||||
* |
||||
* |
||||
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* IDENTIFICATION |
||||
* src/backend/access/spgist/spgproc.c |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include <math.h> |
||||
|
||||
#include "access/spgist_private.h" |
||||
#include "utils/builtins.h" |
||||
#include "utils/float.h" |
||||
#include "utils/geo_decls.h" |
||||
|
||||
#define point_point_distance(p1,p2) \ |
||||
DatumGetFloat8(DirectFunctionCall2(point_distance, \
|
||||
PointPGetDatum(p1), PointPGetDatum(p2))) |
||||
|
||||
/* Point-box distance in the assumption that box is aligned by axis */ |
||||
static double |
||||
point_box_distance(Point *point, BOX *box) |
||||
{ |
||||
double dx, |
||||
dy; |
||||
|
||||
if (isnan(point->x) || isnan(box->low.x) || |
||||
isnan(point->y) || isnan(box->low.y)) |
||||
return get_float8_nan(); |
||||
|
||||
if (point->x < box->low.x) |
||||
dx = box->low.x - point->x; |
||||
else if (point->x > box->high.x) |
||||
dx = point->x - box->high.x; |
||||
else |
||||
dx = 0.0; |
||||
|
||||
if (point->y < box->low.y) |
||||
dy = box->low.y - point->y; |
||||
else if (point->y > box->high.y) |
||||
dy = point->y - box->high.y; |
||||
else |
||||
dy = 0.0; |
||||
|
||||
return HYPOT(dx, dy); |
||||
} |
||||
|
||||
/*
|
||||
* Returns distances from given key to array of ordering scan keys. Leaf key |
||||
* is expected to be point, non-leaf key is expected to be box. Scan key |
||||
* arguments are expected to be points. |
||||
*/ |
||||
double * |
||||
spg_key_orderbys_distances(Datum key, bool isLeaf, |
||||
ScanKey orderbys, int norderbys) |
||||
{ |
||||
int sk_num; |
||||
double *distances = (double *) palloc(norderbys * sizeof(double)), |
||||
*distance = distances; |
||||
|
||||
for (sk_num = 0; sk_num < norderbys; ++sk_num, ++orderbys, ++distance) |
||||
{ |
||||
Point *point = DatumGetPointP(orderbys->sk_argument); |
||||
|
||||
*distance = isLeaf ? point_point_distance(point, DatumGetPointP(key)) |
||||
: point_box_distance(point, DatumGetBoxP(key)); |
||||
} |
||||
|
||||
return distances; |
||||
} |
||||
|
||||
BOX * |
||||
box_copy(BOX *orig) |
||||
{ |
||||
BOX *result = palloc(sizeof(BOX)); |
||||
|
||||
*result = *orig; |
||||
return result; |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue