*/
int coord = PG_GETARG_INT32(1);
bool isLeaf = GistPageIsLeaf(entry->page);
+ bool inverse = false;
/* 0 is the only unsupported coordinate value */
- if (coord <= 0)
+ if (coord == 0)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
- errmsg("cube index %d is out of bounds", coord)));
+ 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))
{
/*
* 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.
+ * be as small as our lower bound. For inversed case we
+ * return upper bound because it becomes lower bound for
+ * inversed value.
*/
- retval = Min(cube->x[index], cube->x[index + DIM(cube)]);
+ if (!inverse)
+ retval = Min(cube->x[index], cube->x[index + DIM(cube)]);
+ else
+ retval = Max(cube->x[index], cube->x[index + DIM(cube)]);
}
}
}
{
retval = 0.0;
}
+
+ /* Inverse return value if needed */
+ if (inverse)
+ retval = -retval;
}
else
{
* getter. Moreover, indexed dataset may contain cubes of different dimensions
* number. Accordingly, this coordinate getter should be able to return
* lower/upper bound for particular dimension independently on number of cube
- * dimensions.
+ * dimensions. Also, KNN-GiST supports only ascending sorting. In order to
+ * support descending sorting, this function returns inverse of value when
+ * negative coordinate is given.
*
* Long story short, this function uses following meaning of coordinates:
* # (2 * N - 1) -- lower bound of Nth dimension,
- * # (2 * N) -- upper bound of Nth dimension.
+ * # (2 * N) -- upper bound of Nth dimension,
+ * # - (2 * N - 1) -- negative of lower bound of Nth dimension,
+ * # - (2 * N) -- negative of upper bound of Nth dimension.
*
* When given coordinate exceeds number of cube dimensions, then 0 returned
* (reproducing logic of GiST indexing of variable-length cubes).
float8 result;
/* 0 is the only unsupported coordinate value */
- if (coord <= 0)
+ if (coord == 0)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
- errmsg("cube index %d is out of bounds", coord)));
+ 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))
{
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>0;
-ERROR: cube index 0 is out of bounds
+ERROR: zero cube index is not defined
SELECT cube(array[40,50,60], array[10,20,30])~>4;
?column?
----------
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>(-1);
-ERROR: cube index -1 is out of bounds
+ ?column?
+----------
+ -10
+(1 row)
+
-- Load some example data and build the index
--
CREATE TABLE test_cube (c cube);
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)
RESET enable_seqscan;
SET enable_indexscan = OFF;
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)
+
RESET enable_indexscan;
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>0;
-ERROR: cube index 0 is out of bounds
+ERROR: zero cube index is not defined
SELECT cube(array[40,50,60], array[10,20,30])~>4;
?column?
----------
(1 row)
SELECT cube(array[40,50,60], array[10,20,30])~>(-1);
-ERROR: cube index -1 is out of bounds
+ ?column?
+----------
+ -10
+(1 row)
+
-- Load some example data and build the index
--
CREATE TABLE test_cube (c cube);
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)
RESET enable_seqscan;
SET enable_indexscan = OFF;
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)
+
RESET enable_indexscan;
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)
RESET enable_seqscan;
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
RESET enable_indexscan;
Get <replaceable>n</replaceable>-th coordinate of cube in following way:
n = 2 * k - 1 means lower bound of <replaceable>k</replaceable>-th
dimension, n = 2 * k means upper bound of
- <replaceable>k</replaceable>-th dimension. This operator is designed
- for KNN-GiST support.
+ <replaceable>k</replaceable>-th dimension. Negative
+ <replaceable>n</replaceable> denotes inversed value of corresponding
+ positive coordinate. This operator is designed for KNN-GiST support.
</entry>
</row>