diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
new file mode 100644
index b770271..d2d67d9
*** a/contrib/cube/cube.c
--- b/contrib/cube/cube.c
*************** g_cube_distance(PG_FUNCTION_ARGS)
*** 1337,1351 ****
if (strategy == CubeKNNDistanceCoord)
{
int coord = PG_GETARG_INT32(1);
! if (DIM(cube) == 0)
! retval = 0.0;
! else if (IS_POINT(cube))
! retval = cube->x[(coord - 1) % DIM(cube)];
else
! retval = Min(cube->x[(coord - 1) % DIM(cube)],
! cube->x[(coord - 1) % DIM(cube) + DIM(cube)]);
}
else
{
--- 1337,1402 ----
if (strategy == CubeKNNDistanceCoord)
{
+ /*
+ * Handle ordering by ~> operator. See comments of cube_coord_llur()
+ * for details
+ */
int coord = PG_GETARG_INT32(1);
+ bool isLeaf = GistPageIsLeaf(entry->page);
+ bool inverse = false;
! /* Return inversed value for negative coordinate */
! if (coord < 0)
! {
! coord = -coord;
! inverse = true;
! }
!
! if (coord <= 2 * DIM(cube))
! {
! /* dimension index */
! int index = (coord - 1) / 2;
! /* whether this is upper bound (lower bound otherwise) */
! bool upper = ((coord - 1) % 2 == 1);
!
! if (IS_POINT(cube))
! {
! retval = cube->x[index];
! }
! else
! {
! if (isLeaf)
! {
! /* For leaf just return required upper/lower bound */
! if (upper)
! retval = Max(cube->x[index], cube->x[index + DIM(cube)]);
! else
! retval = Min(cube->x[index], cube->x[index + DIM(cube)]);
! }
! else
! {
! /*
! * For non-leaf we should always return lower bound,
! * because even upper bound of a child in the subtree can
! * be as small as our lower bound. For inversed case we
! * return upper bound because it becomes lower bound for
! * inversed value.
! */
! if (!inverse)
! retval = Min(cube->x[index], cube->x[index + DIM(cube)]);
! else
! retval = Max(cube->x[index], cube->x[index + DIM(cube)]);
! }
! }
! }
else
! {
! retval = 0.0;
! }
!
! /* Inverse return value if needed */
! if (inverse)
! retval = -retval;
}
else
{
*************** cube_coord(PG_FUNCTION_ARGS)
*** 1492,1534 ****
}
! /*
! * This function works like cube_coord(),
! * but rearranges coordinates of corners to get cube representation
! * in the form of (lower left, upper right).
! * For historical reasons that extension allows us to create cubes in form
! * ((2,1),(1,2)) and instead of normalizing such cube to ((1,1),(2,2)) it
! * stores cube in original way. But to get cubes ordered by one of dimensions
! * directly from the index without extra sort step we need some
! * representation-independent coordinate getter. This function implements it.
*/
Datum
cube_coord_llur(PG_FUNCTION_ARGS)
{
NDBOX *cube = PG_GETARG_NDBOX_P(0);
int coord = PG_GETARG_INT32(1);
! if (coord <= 0 || coord > 2 * DIM(cube))
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
! errmsg("cube index %d is out of bounds", coord)));
! if (coord <= DIM(cube))
{
if (IS_POINT(cube))
! PG_RETURN_FLOAT8(cube->x[coord - 1]);
else
! PG_RETURN_FLOAT8(Min(cube->x[coord - 1],
! cube->x[coord - 1 + DIM(cube)]));
}
else
{
! if (IS_POINT(cube))
! PG_RETURN_FLOAT8(cube->x[(coord - 1) % DIM(cube)]);
! else
! PG_RETURN_FLOAT8(Max(cube->x[coord - 1],
! cube->x[coord - 1 - DIM(cube)]));
}
}
/* Increase or decrease box size by a radius in at least n dimensions. */
--- 1543,1625 ----
}
! /*----
! * This function works like cube_coord(), but rearranges coordinates in the
! * way suitable to support coordinate ordering using KNN-GiST. For historical
! * reasons this extension allows us to create cubes in form ((2,1),(1,2)) and
! * instead of normalizing such cube to ((1,1),(2,2)) it stores cube in original
! * way. But in order to get cubes ordered by one of dimensions from the index
! * without explicit sort step we need this representation-independent coordinate
! * getter. Moreover, indexed dataset may contain cubes of different dimensions
! * number. Accordingly, this corrdinate getter should be able to return
! * lower/upper bound for particular dimension independently on number of cube
! * dimenstions. Also, KNN-GiST supports only ascending sorting. In order to
! * support descinding sorting, this function returns inverse of value when
! * negative coordinate is given.
! *
! * Long stoty short, this function uses following meaning of coordinates:
! * # (2 * N - 1) -- lower bound of Nth dimension,
! * # (2 * N) -- upper bound of Nth dimenstion,
! * # - (2 * N - 1) -- negative of lower bound of Nth dimension,
! * # - (2 * N) -- negative of upper bound of Nth dimenstion.
! *
! * When given coordinate exceeds number of cube dimensions, then 0 returned
! * (reproducing logic of GiST indexing of variable-length cubes).
*/
Datum
cube_coord_llur(PG_FUNCTION_ARGS)
{
NDBOX *cube = PG_GETARG_NDBOX_P(0);
int coord = PG_GETARG_INT32(1);
+ bool inverse = false;
+ float8 result;
! /* 0 is the only unsupported coordinate value */
! if (coord == 0)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
! errmsg("zero cube index is not defined")));
! /* Return inversed value for negative coordinate */
! if (coord < 0)
{
+ coord = -coord;
+ inverse = true;
+ }
+
+ if (coord <= 2 * DIM(cube))
+ {
+ /* dimension index */
+ int index = (coord - 1) / 2;
+ /* whether this is upper bound (lower bound otherwise) */
+ bool upper = ((coord - 1) % 2 == 1);
+
if (IS_POINT(cube))
! {
! result = cube->x[index];
! }
else
! {
! if (upper)
! result = Max(cube->x[index], cube->x[index + DIM(cube)]);
! else
! result = Min(cube->x[index], cube->x[index + DIM(cube)]);
! }
}
else
{
! /*
! * Return zero if coordinate is out of bound. That reproduces logic of
! * how cubes with low dimension number are expanded duing GiST indexing.
! */
! result = 0.0;
}
+
+ /* Inverse value if needed */
+ if (inverse)
+ result = -result;
+
+ PG_RETURN_FLOAT8(result);
}
/* Increase or decrease box size by a radius in at least n dimensions. */
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
new file mode 100644
index 328b3b5..b6a694e
*** a/contrib/cube/expected/cube.out
--- b/contrib/cube/expected/cube.out
*************** SELECT cube(array[40,50,60], array[10,20
*** 1532,1568 ****
SELECT cube(array[10,20,30], array[40,50,60])~>2;
?column?
----------
! 20
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>2;
?column?
----------
! 20
(1 row)
SELECT cube(array[10,20,30], array[40,50,60])~>3;
?column?
----------
! 30
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>3;
?column?
----------
! 30
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>0;
! ERROR: cube index 0 is out of bounds
SELECT cube(array[40,50,60], array[10,20,30])~>4;
?column?
----------
! 40
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>(-1);
! ERROR: cube index -1 is out of bounds
-- Load some example data and build the index
--
CREATE TABLE test_cube (c cube);
--- 1532,1572 ----
SELECT cube(array[10,20,30], array[40,50,60])~>2;
?column?
----------
! 40
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>2;
?column?
----------
! 40
(1 row)
SELECT cube(array[10,20,30], array[40,50,60])~>3;
?column?
----------
! 20
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>3;
?column?
----------
! 20
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>0;
! ERROR: zero cube index is not defined
SELECT cube(array[40,50,60], array[10,20,30])~>4;
?column?
----------
! 50
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>(-1);
! ?column?
! ----------
! -10
! (1 row)
!
-- Load some example data and build the index
--
CREATE TABLE test_cube (c cube);
*************** SELECT * FROM test_cube WHERE c && '(300
*** 1589,1747 ****
(2424, 160),(2424, 81)
(5 rows)
! -- kNN with index
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------------------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 772.000647668122
(1444, 403),(1346, 344) | 846
- (369, 1457),(278, 1409) | 909
(5 rows)
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 656
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
- (948, 1201),(907, 1156) | 1063
(5 rows)
! -- kNN-based sorting
! SELECT * FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by 1st coordinate of lower left corner
! c
! ---------------------------
! (54, 38679),(3, 38602)
! (83, 10271),(15, 10265)
! (122, 46832),(64, 46762)
! (167, 17214),(92, 17184)
! (161, 24465),(107, 24374)
! (162, 26040),(120, 25963)
! (154, 4019),(138, 3990)
! (259, 1850),(175, 1820)
! (207, 40886),(179, 40879)
! (288, 49588),(204, 49571)
! (270, 32616),(226, 32607)
! (318, 31489),(235, 31404)
! (337, 455),(240, 359)
! (270, 29508),(264, 29440)
! (369, 1457),(278, 1409)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by 2nd coordinate or upper right corner
! c
! ---------------------------
! (30333, 50),(30273, 6)
! (43301, 75),(43227, 43)
! (19650, 142),(19630, 51)
! (2424, 160),(2424, 81)
! (3449, 171),(3354, 108)
! (18037, 155),(17941, 109)
! (28511, 208),(28479, 114)
! (19946, 217),(19941, 118)
! (16906, 191),(16816, 139)
! (759, 187),(662, 163)
! (22684, 266),(22656, 181)
! (24423, 255),(24360, 213)
! (45989, 249),(45910, 222)
! (11399, 377),(11360, 294)
! (12162, 389),(12103, 309)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>1 DESC LIMIT 15; -- descending by 1st coordinate of lower left corner
! c
! -------------------------------
! (50027, 49230),(49951, 49214)
! (49980, 35004),(49937, 34963)
! (49985, 6436),(49927, 6338)
! (49999, 27218),(49908, 27176)
! (49954, 1340),(49905, 1294)
! (49944, 25163),(49902, 25153)
! (49981, 34876),(49898, 34786)
! (49957, 43390),(49897, 43384)
! (49853, 18504),(49848, 18503)
! (49902, 41752),(49818, 41746)
! (49907, 30225),(49810, 30158)
! (49843, 5175),(49808, 5145)
! (49887, 24274),(49805, 24184)
! (49847, 7128),(49798, 7067)
! (49820, 7990),(49771, 7967)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>4 DESC LIMIT 15; -- descending by 2nd coordinate or upper right corner
! c
! -------------------------------
! (36311, 50073),(36258, 49987)
! (30746, 50040),(30727, 49992)
! (2168, 50012),(2108, 49914)
! (21551, 49983),(21492, 49885)
! (17954, 49975),(17865, 49915)
! (3531, 49962),(3463, 49934)
! (19128, 49932),(19112, 49849)
! (31287, 49923),(31236, 49913)
! (43925, 49912),(43888, 49878)
! (29261, 49910),(29247, 49818)
! (14913, 49873),(14849, 49836)
! (20007, 49858),(19921, 49778)
! (38266, 49852),(38233, 49844)
! (37595, 49849),(37581, 49834)
! (46151, 49848),(46058, 49830)
(15 rows)
! -- same thing for index with points
! CREATE TABLE test_point(c cube);
! INSERT INTO test_point(SELECT cube(array[c->1,c->2,c->3,c->4]) FROM test_cube);
! CREATE INDEX ON test_point USING gist(c);
! SELECT * FROM test_point ORDER BY c~>1, c~>2 LIMIT 15; -- ascending by 1st then by 2nd coordinate
! c
! --------------------------
! (54, 38679, 3, 38602)
! (83, 10271, 15, 10265)
! (122, 46832, 64, 46762)
! (154, 4019, 138, 3990)
! (161, 24465, 107, 24374)
! (162, 26040, 120, 25963)
! (167, 17214, 92, 17184)
! (207, 40886, 179, 40879)
! (259, 1850, 175, 1820)
! (270, 29508, 264, 29440)
! (270, 32616, 226, 32607)
! (288, 49588, 204, 49571)
! (318, 31489, 235, 31404)
! (326, 18837, 285, 18817)
! (337, 455, 240, 359)
(15 rows)
! SELECT * FROM test_point ORDER BY c~>4 DESC LIMIT 15; -- descending by 1st coordinate
! c
! ------------------------------
! (30746, 50040, 30727, 49992)
! (36311, 50073, 36258, 49987)
! (3531, 49962, 3463, 49934)
! (17954, 49975, 17865, 49915)
! (2168, 50012, 2108, 49914)
! (31287, 49923, 31236, 49913)
! (21551, 49983, 21492, 49885)
! (43925, 49912, 43888, 49878)
! (19128, 49932, 19112, 49849)
! (38266, 49852, 38233, 49844)
! (14913, 49873, 14849, 49836)
! (37595, 49849, 37581, 49834)
! (46151, 49848, 46058, 49830)
! (29261, 49910, 29247, 49818)
! (19233, 49824, 19185, 49794)
(15 rows)
--- 1593,1984 ----
(2424, 160),(2424, 81)
(5 rows)
! -- Test kNN
! INSERT INTO test_cube VALUES ('(1,1)'), ('(100000)'), ('(0, 100000)'); -- Some corner cases
! SET enable_seqscan = OFF;
! SET enable_indexscan = ON;
! -- Test different metrics
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------------------
(337, 455),(240, 359) | 0
+ (1, 1) | 140.007142674936
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 772.000647668122
(1444, 403),(1346, 344) | 846
(5 rows)
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
+ (1, 1) | 99
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 656
(1444, 403),(1346, 344) | 846
+ (5 rows)
+
+ SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------
+ (337, 455),(240, 359) | 0
+ (759, 187),(662, 163) | 162
+ (1, 1) | 198
+ (1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
+ -- Test sorting by coordinates
+ SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (0, 100000)
+ 1 | (1, 1)
+ 3 | (54, 38679),(3, 38602)
+ 15 | (83, 10271),(15, 10265)
+ 64 | (122, 46832),(64, 46762)
+ 92 | (167, 17214),(92, 17184)
+ 107 | (161, 24465),(107, 24374)
+ 120 | (162, 26040),(120, 25963)
+ 138 | (154, 4019),(138, 3990)
+ 175 | (259, 1850),(175, 1820)
+ 179 | (207, 40886),(179, 40879)
+ 204 | (288, 49588),(204, 49571)
+ 226 | (270, 32616),(226, 32607)
+ 235 | (318, 31489),(235, 31404)
+ 240 | (337, 455),(240, 359)
+ (15 rows)
+
+ SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (0, 100000)
+ 1 | (1, 1)
+ 54 | (54, 38679),(3, 38602)
+ 83 | (83, 10271),(15, 10265)
+ 122 | (122, 46832),(64, 46762)
+ 154 | (154, 4019),(138, 3990)
+ 161 | (161, 24465),(107, 24374)
+ 162 | (162, 26040),(120, 25963)
+ 167 | (167, 17214),(92, 17184)
+ 207 | (207, 40886),(179, 40879)
+ 259 | (259, 1850),(175, 1820)
+ 270 | (270, 29508),(264, 29440)
+ 270 | (270, 32616),(226, 32607)
+ 288 | (288, 49588),(204, 49571)
+ 318 | (318, 31489),(235, 31404)
+ (15 rows)
+
+ SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (100000)
+ 1 | (1, 1)
+ 6 | (30333, 50),(30273, 6)
+ 43 | (43301, 75),(43227, 43)
+ 51 | (19650, 142),(19630, 51)
+ 81 | (2424, 160),(2424, 81)
+ 108 | (3449, 171),(3354, 108)
+ 109 | (18037, 155),(17941, 109)
+ 114 | (28511, 208),(28479, 114)
+ 118 | (19946, 217),(19941, 118)
+ 139 | (16906, 191),(16816, 139)
+ 163 | (759, 187),(662, 163)
+ 181 | (22684, 266),(22656, 181)
+ 213 | (24423, 255),(24360, 213)
+ 222 | (45989, 249),(45910, 222)
+ (15 rows)
+
+ SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (100000)
+ 1 | (1, 1)
+ 50 | (30333, 50),(30273, 6)
+ 75 | (43301, 75),(43227, 43)
+ 142 | (19650, 142),(19630, 51)
+ 155 | (18037, 155),(17941, 109)
+ 160 | (2424, 160),(2424, 81)
+ 171 | (3449, 171),(3354, 108)
+ 187 | (759, 187),(662, 163)
+ 191 | (16906, 191),(16816, 139)
+ 208 | (28511, 208),(28479, 114)
+ 217 | (19946, 217),(19941, 118)
+ 249 | (45989, 249),(45910, 222)
+ 255 | (24423, 255),(24360, 213)
+ 266 | (22684, 266),(22656, 181)
+ (15 rows)
+
+ SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (100000)
+ -49951 | (50027, 49230),(49951, 49214)
+ -49937 | (49980, 35004),(49937, 34963)
+ -49927 | (49985, 6436),(49927, 6338)
+ -49908 | (49999, 27218),(49908, 27176)
+ -49905 | (49954, 1340),(49905, 1294)
+ -49902 | (49944, 25163),(49902, 25153)
+ -49898 | (49981, 34876),(49898, 34786)
+ -49897 | (49957, 43390),(49897, 43384)
+ -49848 | (49853, 18504),(49848, 18503)
+ -49818 | (49902, 41752),(49818, 41746)
+ -49810 | (49907, 30225),(49810, 30158)
+ -49808 | (49843, 5175),(49808, 5145)
+ -49805 | (49887, 24274),(49805, 24184)
+ -49798 | (49847, 7128),(49798, 7067)
+ (15 rows)
+
+ SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (100000)
+ -50027 | (50027, 49230),(49951, 49214)
+ -49999 | (49999, 27218),(49908, 27176)
+ -49985 | (49985, 6436),(49927, 6338)
+ -49981 | (49981, 34876),(49898, 34786)
+ -49980 | (49980, 35004),(49937, 34963)
+ -49957 | (49957, 43390),(49897, 43384)
+ -49954 | (49954, 1340),(49905, 1294)
+ -49944 | (49944, 25163),(49902, 25153)
+ -49907 | (49907, 30225),(49810, 30158)
+ -49902 | (49902, 41752),(49818, 41746)
+ -49887 | (49887, 24274),(49805, 24184)
+ -49853 | (49853, 18504),(49848, 18503)
+ -49847 | (49847, 7128),(49798, 7067)
+ -49843 | (49843, 5175),(49808, 5145)
+ (15 rows)
+
+ SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (0, 100000)
+ -49992 | (30746, 50040),(30727, 49992)
+ -49987 | (36311, 50073),(36258, 49987)
+ -49934 | (3531, 49962),(3463, 49934)
+ -49915 | (17954, 49975),(17865, 49915)
+ -49914 | (2168, 50012),(2108, 49914)
+ -49913 | (31287, 49923),(31236, 49913)
+ -49885 | (21551, 49983),(21492, 49885)
+ -49878 | (43925, 49912),(43888, 49878)
+ -49849 | (19128, 49932),(19112, 49849)
+ -49844 | (38266, 49852),(38233, 49844)
+ -49836 | (14913, 49873),(14849, 49836)
+ -49834 | (37595, 49849),(37581, 49834)
+ -49830 | (46151, 49848),(46058, 49830)
+ -49818 | (29261, 49910),(29247, 49818)
+ (15 rows)
+
+ SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (0, 100000)
+ -50073 | (36311, 50073),(36258, 49987)
+ -50040 | (30746, 50040),(30727, 49992)
+ -50012 | (2168, 50012),(2108, 49914)
+ -49983 | (21551, 49983),(21492, 49885)
+ -49975 | (17954, 49975),(17865, 49915)
+ -49962 | (3531, 49962),(3463, 49934)
+ -49932 | (19128, 49932),(19112, 49849)
+ -49923 | (31287, 49923),(31236, 49913)
+ -49912 | (43925, 49912),(43888, 49878)
+ -49910 | (29261, 49910),(29247, 49818)
+ -49873 | (14913, 49873),(14849, 49836)
+ -49858 | (20007, 49858),(19921, 49778)
+ -49852 | (38266, 49852),(38233, 49844)
+ -49849 | (37595, 49849),(37581, 49834)
+ (15 rows)
+
+ -- Same queries with sequential scan (should give the same results as above)
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------------------
+ (337, 455),(240, 359) | 0
+ (1, 1) | 140.007142674936
+ (759, 187),(662, 163) | 162
+ (948, 1201),(907, 1156) | 772.000647668122
+ (1444, 403),(1346, 344) | 846
+ (5 rows)
+
+ SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------
+ (337, 455),(240, 359) | 0
+ (1, 1) | 99
+ (759, 187),(662, 163) | 162
+ (948, 1201),(907, 1156) | 656
+ (1444, 403),(1346, 344) | 846
+ (5 rows)
+
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
+ (1, 1) | 198
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
! SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
! ?column? | c
! ----------+---------------------------
! 0 | (0, 100000)
! 1 | (1, 1)
! 3 | (54, 38679),(3, 38602)
! 15 | (83, 10271),(15, 10265)
! 64 | (122, 46832),(64, 46762)
! 92 | (167, 17214),(92, 17184)
! 107 | (161, 24465),(107, 24374)
! 120 | (162, 26040),(120, 25963)
! 138 | (154, 4019),(138, 3990)
! 175 | (259, 1850),(175, 1820)
! 179 | (207, 40886),(179, 40879)
! 204 | (288, 49588),(204, 49571)
! 226 | (270, 32616),(226, 32607)
! 235 | (318, 31489),(235, 31404)
! 240 | (337, 455),(240, 359)
(15 rows)
! SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
! ?column? | c
! ----------+---------------------------
! 0 | (0, 100000)
! 1 | (1, 1)
! 54 | (54, 38679),(3, 38602)
! 83 | (83, 10271),(15, 10265)
! 122 | (122, 46832),(64, 46762)
! 154 | (154, 4019),(138, 3990)
! 161 | (161, 24465),(107, 24374)
! 162 | (162, 26040),(120, 25963)
! 167 | (167, 17214),(92, 17184)
! 207 | (207, 40886),(179, 40879)
! 259 | (259, 1850),(175, 1820)
! 270 | (270, 29508),(264, 29440)
! 270 | (270, 32616),(226, 32607)
! 288 | (288, 49588),(204, 49571)
! 318 | (318, 31489),(235, 31404)
(15 rows)
! SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
! ?column? | c
! ----------+---------------------------
! 0 | (100000)
! 1 | (1, 1)
! 6 | (30333, 50),(30273, 6)
! 43 | (43301, 75),(43227, 43)
! 51 | (19650, 142),(19630, 51)
! 81 | (2424, 160),(2424, 81)
! 108 | (3449, 171),(3354, 108)
! 109 | (18037, 155),(17941, 109)
! 114 | (28511, 208),(28479, 114)
! 118 | (19946, 217),(19941, 118)
! 139 | (16906, 191),(16816, 139)
! 163 | (759, 187),(662, 163)
! 181 | (22684, 266),(22656, 181)
! 213 | (24423, 255),(24360, 213)
! 222 | (45989, 249),(45910, 222)
(15 rows)
! SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
! ?column? | c
! ----------+---------------------------
! 0 | (100000)
! 1 | (1, 1)
! 50 | (30333, 50),(30273, 6)
! 75 | (43301, 75),(43227, 43)
! 142 | (19650, 142),(19630, 51)
! 155 | (18037, 155),(17941, 109)
! 160 | (2424, 160),(2424, 81)
! 171 | (3449, 171),(3354, 108)
! 187 | (759, 187),(662, 163)
! 191 | (16906, 191),(16816, 139)
! 208 | (28511, 208),(28479, 114)
! 217 | (19946, 217),(19941, 118)
! 249 | (45989, 249),(45910, 222)
! 255 | (24423, 255),(24360, 213)
! 266 | (22684, 266),(22656, 181)
(15 rows)
! SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (100000)
! -49951 | (50027, 49230),(49951, 49214)
! -49937 | (49980, 35004),(49937, 34963)
! -49927 | (49985, 6436),(49927, 6338)
! -49908 | (49999, 27218),(49908, 27176)
! -49905 | (49954, 1340),(49905, 1294)
! -49902 | (49944, 25163),(49902, 25153)
! -49898 | (49981, 34876),(49898, 34786)
! -49897 | (49957, 43390),(49897, 43384)
! -49848 | (49853, 18504),(49848, 18503)
! -49818 | (49902, 41752),(49818, 41746)
! -49810 | (49907, 30225),(49810, 30158)
! -49808 | (49843, 5175),(49808, 5145)
! -49805 | (49887, 24274),(49805, 24184)
! -49798 | (49847, 7128),(49798, 7067)
(15 rows)
! SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (100000)
! -50027 | (50027, 49230),(49951, 49214)
! -49999 | (49999, 27218),(49908, 27176)
! -49985 | (49985, 6436),(49927, 6338)
! -49981 | (49981, 34876),(49898, 34786)
! -49980 | (49980, 35004),(49937, 34963)
! -49957 | (49957, 43390),(49897, 43384)
! -49954 | (49954, 1340),(49905, 1294)
! -49944 | (49944, 25163),(49902, 25153)
! -49907 | (49907, 30225),(49810, 30158)
! -49902 | (49902, 41752),(49818, 41746)
! -49887 | (49887, 24274),(49805, 24184)
! -49853 | (49853, 18504),(49848, 18503)
! -49847 | (49847, 7128),(49798, 7067)
! -49843 | (49843, 5175),(49808, 5145)
! (15 rows)
!
! SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (0, 100000)
! -49992 | (30746, 50040),(30727, 49992)
! -49987 | (36311, 50073),(36258, 49987)
! -49934 | (3531, 49962),(3463, 49934)
! -49915 | (17954, 49975),(17865, 49915)
! -49914 | (2168, 50012),(2108, 49914)
! -49913 | (31287, 49923),(31236, 49913)
! -49885 | (21551, 49983),(21492, 49885)
! -49878 | (43925, 49912),(43888, 49878)
! -49849 | (19128, 49932),(19112, 49849)
! -49844 | (38266, 49852),(38233, 49844)
! -49836 | (14913, 49873),(14849, 49836)
! -49834 | (37595, 49849),(37581, 49834)
! -49830 | (46151, 49848),(46058, 49830)
! -49818 | (29261, 49910),(29247, 49818)
! (15 rows)
!
! SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (0, 100000)
! -50073 | (36311, 50073),(36258, 49987)
! -50040 | (30746, 50040),(30727, 49992)
! -50012 | (2168, 50012),(2108, 49914)
! -49983 | (21551, 49983),(21492, 49885)
! -49975 | (17954, 49975),(17865, 49915)
! -49962 | (3531, 49962),(3463, 49934)
! -49932 | (19128, 49932),(19112, 49849)
! -49923 | (31287, 49923),(31236, 49913)
! -49912 | (43925, 49912),(43888, 49878)
! -49910 | (29261, 49910),(29247, 49818)
! -49873 | (14913, 49873),(14849, 49836)
! -49858 | (20007, 49858),(19921, 49778)
! -49852 | (38266, 49852),(38233, 49844)
! -49849 | (37595, 49849),(37581, 49834)
(15 rows)
diff --git a/contrib/cube/expected/cube_2.out b/contrib/cube/expected/cube_2.out
new file mode 100644
index 1aa5cf2..c6ce3a3
*** a/contrib/cube/expected/cube_2.out
--- b/contrib/cube/expected/cube_2.out
*************** SELECT * FROM test_cube WHERE c && '(300
*** 1589,1747 ****
(2424, 160),(2424, 81)
(5 rows)
! -- kNN with index
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------------------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 772.000647668122
(1444, 403),(1346, 344) | 846
- (369, 1457),(278, 1409) | 909
(5 rows)
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 656
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
- (948, 1201),(907, 1156) | 1063
(5 rows)
! -- kNN-based sorting
! SELECT * FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by 1st coordinate of lower left corner
! c
! ---------------------------
! (54, 38679),(3, 38602)
! (83, 10271),(15, 10265)
! (122, 46832),(64, 46762)
! (167, 17214),(92, 17184)
! (161, 24465),(107, 24374)
! (162, 26040),(120, 25963)
! (154, 4019),(138, 3990)
! (259, 1850),(175, 1820)
! (207, 40886),(179, 40879)
! (288, 49588),(204, 49571)
! (270, 32616),(226, 32607)
! (318, 31489),(235, 31404)
! (337, 455),(240, 359)
! (270, 29508),(264, 29440)
! (369, 1457),(278, 1409)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by 2nd coordinate or upper right corner
! c
! ---------------------------
! (30333, 50),(30273, 6)
! (43301, 75),(43227, 43)
! (19650, 142),(19630, 51)
! (2424, 160),(2424, 81)
! (3449, 171),(3354, 108)
! (18037, 155),(17941, 109)
! (28511, 208),(28479, 114)
! (19946, 217),(19941, 118)
! (16906, 191),(16816, 139)
! (759, 187),(662, 163)
! (22684, 266),(22656, 181)
! (24423, 255),(24360, 213)
! (45989, 249),(45910, 222)
! (11399, 377),(11360, 294)
! (12162, 389),(12103, 309)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>1 DESC LIMIT 15; -- descending by 1st coordinate of lower left corner
! c
! -------------------------------
! (50027, 49230),(49951, 49214)
! (49980, 35004),(49937, 34963)
! (49985, 6436),(49927, 6338)
! (49999, 27218),(49908, 27176)
! (49954, 1340),(49905, 1294)
! (49944, 25163),(49902, 25153)
! (49981, 34876),(49898, 34786)
! (49957, 43390),(49897, 43384)
! (49853, 18504),(49848, 18503)
! (49902, 41752),(49818, 41746)
! (49907, 30225),(49810, 30158)
! (49843, 5175),(49808, 5145)
! (49887, 24274),(49805, 24184)
! (49847, 7128),(49798, 7067)
! (49820, 7990),(49771, 7967)
(15 rows)
! SELECT * FROM test_cube ORDER BY c~>4 DESC LIMIT 15; -- descending by 2nd coordinate or upper right corner
! c
! -------------------------------
! (36311, 50073),(36258, 49987)
! (30746, 50040),(30727, 49992)
! (2168, 50012),(2108, 49914)
! (21551, 49983),(21492, 49885)
! (17954, 49975),(17865, 49915)
! (3531, 49962),(3463, 49934)
! (19128, 49932),(19112, 49849)
! (31287, 49923),(31236, 49913)
! (43925, 49912),(43888, 49878)
! (29261, 49910),(29247, 49818)
! (14913, 49873),(14849, 49836)
! (20007, 49858),(19921, 49778)
! (38266, 49852),(38233, 49844)
! (37595, 49849),(37581, 49834)
! (46151, 49848),(46058, 49830)
(15 rows)
! -- same thing for index with points
! CREATE TABLE test_point(c cube);
! INSERT INTO test_point(SELECT cube(array[c->1,c->2,c->3,c->4]) FROM test_cube);
! CREATE INDEX ON test_point USING gist(c);
! SELECT * FROM test_point ORDER BY c~>1, c~>2 LIMIT 15; -- ascending by 1st then by 2nd coordinate
! c
! --------------------------
! (54, 38679, 3, 38602)
! (83, 10271, 15, 10265)
! (122, 46832, 64, 46762)
! (154, 4019, 138, 3990)
! (161, 24465, 107, 24374)
! (162, 26040, 120, 25963)
! (167, 17214, 92, 17184)
! (207, 40886, 179, 40879)
! (259, 1850, 175, 1820)
! (270, 29508, 264, 29440)
! (270, 32616, 226, 32607)
! (288, 49588, 204, 49571)
! (318, 31489, 235, 31404)
! (326, 18837, 285, 18817)
! (337, 455, 240, 359)
(15 rows)
! SELECT * FROM test_point ORDER BY c~>4 DESC LIMIT 15; -- descending by 1st coordinate
! c
! ------------------------------
! (30746, 50040, 30727, 49992)
! (36311, 50073, 36258, 49987)
! (3531, 49962, 3463, 49934)
! (17954, 49975, 17865, 49915)
! (2168, 50012, 2108, 49914)
! (31287, 49923, 31236, 49913)
! (21551, 49983, 21492, 49885)
! (43925, 49912, 43888, 49878)
! (19128, 49932, 19112, 49849)
! (38266, 49852, 38233, 49844)
! (14913, 49873, 14849, 49836)
! (37595, 49849, 37581, 49834)
! (46151, 49848, 46058, 49830)
! (29261, 49910, 29247, 49818)
! (19233, 49824, 19185, 49794)
(15 rows)
--- 1589,1980 ----
(2424, 160),(2424, 81)
(5 rows)
! -- Test kNN
! INSERT INTO test_cube VALUES ('(1,1)'), ('(100000)'), ('(0, 100000)'); -- Some corner cases
! SET enable_seqscan = OFF;
! SET enable_indexscan = ON;
! -- Test different metrics
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------------------
(337, 455),(240, 359) | 0
+ (1, 1) | 140.007142674936
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 772.000647668122
(1444, 403),(1346, 344) | 846
(5 rows)
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
+ (1, 1) | 99
(759, 187),(662, 163) | 162
(948, 1201),(907, 1156) | 656
(1444, 403),(1346, 344) | 846
+ (5 rows)
+
+ SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------
+ (337, 455),(240, 359) | 0
+ (759, 187),(662, 163) | 162
+ (1, 1) | 198
+ (1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
+ -- Test sorting by coordinates
+ SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (0, 100000)
+ 1 | (1, 1)
+ 3 | (54, 38679),(3, 38602)
+ 15 | (83, 10271),(15, 10265)
+ 64 | (122, 46832),(64, 46762)
+ 92 | (167, 17214),(92, 17184)
+ 107 | (161, 24465),(107, 24374)
+ 120 | (162, 26040),(120, 25963)
+ 138 | (154, 4019),(138, 3990)
+ 175 | (259, 1850),(175, 1820)
+ 179 | (207, 40886),(179, 40879)
+ 204 | (288, 49588),(204, 49571)
+ 226 | (270, 32616),(226, 32607)
+ 235 | (318, 31489),(235, 31404)
+ 240 | (337, 455),(240, 359)
+ (15 rows)
+
+ SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (0, 100000)
+ 1 | (1, 1)
+ 54 | (54, 38679),(3, 38602)
+ 83 | (83, 10271),(15, 10265)
+ 122 | (122, 46832),(64, 46762)
+ 154 | (154, 4019),(138, 3990)
+ 161 | (161, 24465),(107, 24374)
+ 162 | (162, 26040),(120, 25963)
+ 167 | (167, 17214),(92, 17184)
+ 207 | (207, 40886),(179, 40879)
+ 259 | (259, 1850),(175, 1820)
+ 270 | (270, 29508),(264, 29440)
+ 270 | (270, 32616),(226, 32607)
+ 288 | (288, 49588),(204, 49571)
+ 318 | (318, 31489),(235, 31404)
+ (15 rows)
+
+ SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (100000)
+ 1 | (1, 1)
+ 6 | (30333, 50),(30273, 6)
+ 43 | (43301, 75),(43227, 43)
+ 51 | (19650, 142),(19630, 51)
+ 81 | (2424, 160),(2424, 81)
+ 108 | (3449, 171),(3354, 108)
+ 109 | (18037, 155),(17941, 109)
+ 114 | (28511, 208),(28479, 114)
+ 118 | (19946, 217),(19941, 118)
+ 139 | (16906, 191),(16816, 139)
+ 163 | (759, 187),(662, 163)
+ 181 | (22684, 266),(22656, 181)
+ 213 | (24423, 255),(24360, 213)
+ 222 | (45989, 249),(45910, 222)
+ (15 rows)
+
+ SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
+ ?column? | c
+ ----------+---------------------------
+ 0 | (100000)
+ 1 | (1, 1)
+ 50 | (30333, 50),(30273, 6)
+ 75 | (43301, 75),(43227, 43)
+ 142 | (19650, 142),(19630, 51)
+ 155 | (18037, 155),(17941, 109)
+ 160 | (2424, 160),(2424, 81)
+ 171 | (3449, 171),(3354, 108)
+ 187 | (759, 187),(662, 163)
+ 191 | (16906, 191),(16816, 139)
+ 208 | (28511, 208),(28479, 114)
+ 217 | (19946, 217),(19941, 118)
+ 249 | (45989, 249),(45910, 222)
+ 255 | (24423, 255),(24360, 213)
+ 266 | (22684, 266),(22656, 181)
+ (15 rows)
+
+ SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (100000)
+ -49951 | (50027, 49230),(49951, 49214)
+ -49937 | (49980, 35004),(49937, 34963)
+ -49927 | (49985, 6436),(49927, 6338)
+ -49908 | (49999, 27218),(49908, 27176)
+ -49905 | (49954, 1340),(49905, 1294)
+ -49902 | (49944, 25163),(49902, 25153)
+ -49898 | (49981, 34876),(49898, 34786)
+ -49897 | (49957, 43390),(49897, 43384)
+ -49848 | (49853, 18504),(49848, 18503)
+ -49818 | (49902, 41752),(49818, 41746)
+ -49810 | (49907, 30225),(49810, 30158)
+ -49808 | (49843, 5175),(49808, 5145)
+ -49805 | (49887, 24274),(49805, 24184)
+ -49798 | (49847, 7128),(49798, 7067)
+ (15 rows)
+
+ SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (100000)
+ -50027 | (50027, 49230),(49951, 49214)
+ -49999 | (49999, 27218),(49908, 27176)
+ -49985 | (49985, 6436),(49927, 6338)
+ -49981 | (49981, 34876),(49898, 34786)
+ -49980 | (49980, 35004),(49937, 34963)
+ -49957 | (49957, 43390),(49897, 43384)
+ -49954 | (49954, 1340),(49905, 1294)
+ -49944 | (49944, 25163),(49902, 25153)
+ -49907 | (49907, 30225),(49810, 30158)
+ -49902 | (49902, 41752),(49818, 41746)
+ -49887 | (49887, 24274),(49805, 24184)
+ -49853 | (49853, 18504),(49848, 18503)
+ -49847 | (49847, 7128),(49798, 7067)
+ -49843 | (49843, 5175),(49808, 5145)
+ (15 rows)
+
+ SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (0, 100000)
+ -49992 | (30746, 50040),(30727, 49992)
+ -49987 | (36311, 50073),(36258, 49987)
+ -49934 | (3531, 49962),(3463, 49934)
+ -49915 | (17954, 49975),(17865, 49915)
+ -49914 | (2168, 50012),(2108, 49914)
+ -49913 | (31287, 49923),(31236, 49913)
+ -49885 | (21551, 49983),(21492, 49885)
+ -49878 | (43925, 49912),(43888, 49878)
+ -49849 | (19128, 49932),(19112, 49849)
+ -49844 | (38266, 49852),(38233, 49844)
+ -49836 | (14913, 49873),(14849, 49836)
+ -49834 | (37595, 49849),(37581, 49834)
+ -49830 | (46151, 49848),(46058, 49830)
+ -49818 | (29261, 49910),(29247, 49818)
+ (15 rows)
+
+ SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
+ ?column? | c
+ ----------+-------------------------------
+ -100000 | (0, 100000)
+ -50073 | (36311, 50073),(36258, 49987)
+ -50040 | (30746, 50040),(30727, 49992)
+ -50012 | (2168, 50012),(2108, 49914)
+ -49983 | (21551, 49983),(21492, 49885)
+ -49975 | (17954, 49975),(17865, 49915)
+ -49962 | (3531, 49962),(3463, 49934)
+ -49932 | (19128, 49932),(19112, 49849)
+ -49923 | (31287, 49923),(31236, 49913)
+ -49912 | (43925, 49912),(43888, 49878)
+ -49910 | (29261, 49910),(29247, 49818)
+ -49873 | (14913, 49873),(14849, 49836)
+ -49858 | (20007, 49858),(19921, 49778)
+ -49852 | (38266, 49852),(38233, 49844)
+ -49849 | (37595, 49849),(37581, 49834)
+ (15 rows)
+
+ -- Same queries with sequential scan (should give the same results as above)
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------------------
+ (337, 455),(240, 359) | 0
+ (1, 1) | 140.007142674936
+ (759, 187),(662, 163) | 162
+ (948, 1201),(907, 1156) | 772.000647668122
+ (1444, 403),(1346, 344) | 846
+ (5 rows)
+
+ SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
+ c | dist
+ -------------------------+------
+ (337, 455),(240, 359) | 0
+ (1, 1) | 99
+ (759, 187),(662, 163) | 162
+ (948, 1201),(907, 1156) | 656
+ (1444, 403),(1346, 344) | 846
+ (5 rows)
+
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
c | dist
-------------------------+------
(337, 455),(240, 359) | 0
(759, 187),(662, 163) | 162
+ (1, 1) | 198
(1444, 403),(1346, 344) | 846
(369, 1457),(278, 1409) | 909
(5 rows)
! SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
! ?column? | c
! ----------+---------------------------
! 0 | (0, 100000)
! 1 | (1, 1)
! 3 | (54, 38679),(3, 38602)
! 15 | (83, 10271),(15, 10265)
! 64 | (122, 46832),(64, 46762)
! 92 | (167, 17214),(92, 17184)
! 107 | (161, 24465),(107, 24374)
! 120 | (162, 26040),(120, 25963)
! 138 | (154, 4019),(138, 3990)
! 175 | (259, 1850),(175, 1820)
! 179 | (207, 40886),(179, 40879)
! 204 | (288, 49588),(204, 49571)
! 226 | (270, 32616),(226, 32607)
! 235 | (318, 31489),(235, 31404)
! 240 | (337, 455),(240, 359)
(15 rows)
! SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
! ?column? | c
! ----------+---------------------------
! 0 | (0, 100000)
! 1 | (1, 1)
! 54 | (54, 38679),(3, 38602)
! 83 | (83, 10271),(15, 10265)
! 122 | (122, 46832),(64, 46762)
! 154 | (154, 4019),(138, 3990)
! 161 | (161, 24465),(107, 24374)
! 162 | (162, 26040),(120, 25963)
! 167 | (167, 17214),(92, 17184)
! 207 | (207, 40886),(179, 40879)
! 259 | (259, 1850),(175, 1820)
! 270 | (270, 29508),(264, 29440)
! 270 | (270, 32616),(226, 32607)
! 288 | (288, 49588),(204, 49571)
! 318 | (318, 31489),(235, 31404)
(15 rows)
! SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
! ?column? | c
! ----------+---------------------------
! 0 | (100000)
! 1 | (1, 1)
! 6 | (30333, 50),(30273, 6)
! 43 | (43301, 75),(43227, 43)
! 51 | (19650, 142),(19630, 51)
! 81 | (2424, 160),(2424, 81)
! 108 | (3449, 171),(3354, 108)
! 109 | (18037, 155),(17941, 109)
! 114 | (28511, 208),(28479, 114)
! 118 | (19946, 217),(19941, 118)
! 139 | (16906, 191),(16816, 139)
! 163 | (759, 187),(662, 163)
! 181 | (22684, 266),(22656, 181)
! 213 | (24423, 255),(24360, 213)
! 222 | (45989, 249),(45910, 222)
(15 rows)
! SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
! ?column? | c
! ----------+---------------------------
! 0 | (100000)
! 1 | (1, 1)
! 50 | (30333, 50),(30273, 6)
! 75 | (43301, 75),(43227, 43)
! 142 | (19650, 142),(19630, 51)
! 155 | (18037, 155),(17941, 109)
! 160 | (2424, 160),(2424, 81)
! 171 | (3449, 171),(3354, 108)
! 187 | (759, 187),(662, 163)
! 191 | (16906, 191),(16816, 139)
! 208 | (28511, 208),(28479, 114)
! 217 | (19946, 217),(19941, 118)
! 249 | (45989, 249),(45910, 222)
! 255 | (24423, 255),(24360, 213)
! 266 | (22684, 266),(22656, 181)
(15 rows)
! SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (100000)
! -49951 | (50027, 49230),(49951, 49214)
! -49937 | (49980, 35004),(49937, 34963)
! -49927 | (49985, 6436),(49927, 6338)
! -49908 | (49999, 27218),(49908, 27176)
! -49905 | (49954, 1340),(49905, 1294)
! -49902 | (49944, 25163),(49902, 25153)
! -49898 | (49981, 34876),(49898, 34786)
! -49897 | (49957, 43390),(49897, 43384)
! -49848 | (49853, 18504),(49848, 18503)
! -49818 | (49902, 41752),(49818, 41746)
! -49810 | (49907, 30225),(49810, 30158)
! -49808 | (49843, 5175),(49808, 5145)
! -49805 | (49887, 24274),(49805, 24184)
! -49798 | (49847, 7128),(49798, 7067)
(15 rows)
! SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (100000)
! -50027 | (50027, 49230),(49951, 49214)
! -49999 | (49999, 27218),(49908, 27176)
! -49985 | (49985, 6436),(49927, 6338)
! -49981 | (49981, 34876),(49898, 34786)
! -49980 | (49980, 35004),(49937, 34963)
! -49957 | (49957, 43390),(49897, 43384)
! -49954 | (49954, 1340),(49905, 1294)
! -49944 | (49944, 25163),(49902, 25153)
! -49907 | (49907, 30225),(49810, 30158)
! -49902 | (49902, 41752),(49818, 41746)
! -49887 | (49887, 24274),(49805, 24184)
! -49853 | (49853, 18504),(49848, 18503)
! -49847 | (49847, 7128),(49798, 7067)
! -49843 | (49843, 5175),(49808, 5145)
! (15 rows)
!
! SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (0, 100000)
! -49992 | (30746, 50040),(30727, 49992)
! -49987 | (36311, 50073),(36258, 49987)
! -49934 | (3531, 49962),(3463, 49934)
! -49915 | (17954, 49975),(17865, 49915)
! -49914 | (2168, 50012),(2108, 49914)
! -49913 | (31287, 49923),(31236, 49913)
! -49885 | (21551, 49983),(21492, 49885)
! -49878 | (43925, 49912),(43888, 49878)
! -49849 | (19128, 49932),(19112, 49849)
! -49844 | (38266, 49852),(38233, 49844)
! -49836 | (14913, 49873),(14849, 49836)
! -49834 | (37595, 49849),(37581, 49834)
! -49830 | (46151, 49848),(46058, 49830)
! -49818 | (29261, 49910),(29247, 49818)
! (15 rows)
!
! SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
! ?column? | c
! ----------+-------------------------------
! -100000 | (0, 100000)
! -50073 | (36311, 50073),(36258, 49987)
! -50040 | (30746, 50040),(30727, 49992)
! -50012 | (2168, 50012),(2108, 49914)
! -49983 | (21551, 49983),(21492, 49885)
! -49975 | (17954, 49975),(17865, 49915)
! -49962 | (3531, 49962),(3463, 49934)
! -49932 | (19128, 49932),(19112, 49849)
! -49923 | (31287, 49923),(31236, 49913)
! -49912 | (43925, 49912),(43888, 49878)
! -49910 | (29261, 49910),(29247, 49818)
! -49873 | (14913, 49873),(14849, 49836)
! -49858 | (20007, 49858),(19921, 49778)
! -49852 | (38266, 49852),(38233, 49844)
! -49849 | (37595, 49849),(37581, 49834)
(15 rows)
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
new file mode 100644
index 58ea3ad..510d5a7
*** a/contrib/cube/sql/cube.sql
--- b/contrib/cube/sql/cube.sql
*************** SELECT * FROM test_cube WHERE c && '(300
*** 382,401 ****
-- Test sorting
SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
! -- kNN with index
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
! -- kNN-based sorting
! SELECT * FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by 1st coordinate of lower left corner
! SELECT * FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by 2nd coordinate or upper right corner
! SELECT * FROM test_cube ORDER BY c~>1 DESC LIMIT 15; -- descending by 1st coordinate of lower left corner
! SELECT * FROM test_cube ORDER BY c~>4 DESC LIMIT 15; -- descending by 2nd coordinate or upper right corner
! -- same thing for index with points
! CREATE TABLE test_point(c cube);
! INSERT INTO test_point(SELECT cube(array[c->1,c->2,c->3,c->4]) FROM test_cube);
! CREATE INDEX ON test_point USING gist(c);
! SELECT * FROM test_point ORDER BY c~>1, c~>2 LIMIT 15; -- ascending by 1st then by 2nd coordinate
! SELECT * FROM test_point ORDER BY c~>4 DESC LIMIT 15; -- descending by 1st coordinate
--- 382,420 ----
-- Test sorting
SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
! -- Test kNN
! INSERT INTO test_cube VALUES ('(1,1)'), ('(100000)'), ('(0, 100000)'); -- Some corner cases
! SET enable_seqscan = OFF;
! SET enable_indexscan = ON;
!
! -- Test different metrics
SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
! -- Test sorting by coordinates
! SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
! SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
! SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
! SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
! SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
! SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
! SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
! SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
! -- Same queries with sequential scan (should give the same results as above)
! SET enable_seqscan = ON;
! SET enable_indexscan = OFF;
!
! SELECT *, c <-> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <-> '(100, 100),(500, 500)'::cube LIMIT 5;
! SELECT *, c <=> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <=> '(100, 100),(500, 500)'::cube LIMIT 5;
! SELECT *, c <#> '(100, 100),(500, 500)'::cube as dist FROM test_cube ORDER BY c <#> '(100, 100),(500, 500)'::cube LIMIT 5;
!
! SELECT c~>1, c FROM test_cube ORDER BY c~>1 LIMIT 15; -- ascending by left bound
! SELECT c~>2, c FROM test_cube ORDER BY c~>2 LIMIT 15; -- ascending by right bound
! SELECT c~>3, c FROM test_cube ORDER BY c~>3 LIMIT 15; -- ascending by lower bound
! SELECT c~>4, c FROM test_cube ORDER BY c~>4 LIMIT 15; -- ascending by upper bound
! SELECT c~>(-1), c FROM test_cube ORDER BY c~>(-1) LIMIT 15; -- descending by left bound
! SELECT c~>(-2), c FROM test_cube ORDER BY c~>(-2) LIMIT 15; -- descending by right bound
! SELECT c~>(-3), c FROM test_cube ORDER BY c~>(-3) LIMIT 15; -- descending by lower bound
! SELECT c~>(-4), c FROM test_cube ORDER BY c~>(-4) LIMIT 15; -- descending by upper bound
diff --git a/doc/src/sgml/cube.sgml b/doc/src/sgml/cube.sgml
new file mode 100644
index 46d8e4e..65887b1
*** a/doc/src/sgml/cube.sgml
--- b/doc/src/sgml/cube.sgml
***************
*** 186,195 ****
a ~> n
float8
! Get n-th coordinate in normalized
cube
! representation, in which the coordinates have been rearranged into
! the form lower left — upper right
; that is, the
! smaller endpoint along each dimension appears first.
--- 186,197 ----
a ~> n
float8
! Get n-th coordinate of cube in following way:
! n = 2 * k - 1 means lower bound of k-th
! dimension, n = 2 * k means upper bound of
! k-th dimension. Negative
! n denotes inversed value of corresponding
! positive coordinate. This operator is designed for KNN-GiST support.