diff options
-rw-r--r-- | contrib/cube/cube.c | 128 | ||||
-rw-r--r-- | contrib/cube/expected/cube.out | 14 | ||||
-rw-r--r-- | contrib/cube/expected/cube_1.out | 14 | ||||
-rw-r--r-- | contrib/cube/expected/cube_2.out | 14 | ||||
-rw-r--r-- | contrib/cube/expected/cube_3.out | 14 | ||||
-rw-r--r-- | doc/src/sgml/cube.sgml | 199 |
6 files changed, 186 insertions, 197 deletions
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index 35ffb6c3f7a..3feddef8f39 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -1275,6 +1275,7 @@ distance_taxicab(PG_FUNCTION_ARGS) if (DIM(a) < DIM(b)) { NDBOX *tmp = b; + b = a; a = tmp; swapped = true; @@ -1283,11 +1284,13 @@ distance_taxicab(PG_FUNCTION_ARGS) distance = 0.0; /* compute within the dimensions of (b) */ for (i = 0; i < DIM(b); i++) - distance += fabs(distance_1D(LL_COORD(a,i), UR_COORD(a,i), LL_COORD(b,i), UR_COORD(b,i))); + distance += fabs(distance_1D(LL_COORD(a, i), UR_COORD(a, i), + LL_COORD(b, i), UR_COORD(b, i))); /* compute distance to zero for those dimensions in (a) absent in (b) */ for (i = DIM(b); i < DIM(a); i++) - distance += fabs(distance_1D(LL_COORD(a,i), UR_COORD(a,i), 0.0, 0.0)); + distance += fabs(distance_1D(LL_COORD(a, i), UR_COORD(a, i), + 0.0, 0.0)); if (swapped) { @@ -1309,13 +1312,15 @@ distance_chebyshev(PG_FUNCTION_ARGS) NDBOX *a = PG_GETARG_NDBOX(0), *b = PG_GETARG_NDBOX(1); bool swapped = false; - double d, distance; + double d, + distance; int i; /* swap the box pointers if needed */ if (DIM(a) < DIM(b)) { NDBOX *tmp = b; + b = a; a = tmp; swapped = true; @@ -1325,7 +1330,8 @@ distance_chebyshev(PG_FUNCTION_ARGS) /* compute within the dimensions of (b) */ for (i = 0; i < DIM(b); i++) { - d = fabs(distance_1D(LL_COORD(a,i), UR_COORD(a,i), LL_COORD(b,i), UR_COORD(b,i))); + d = fabs(distance_1D(LL_COORD(a, i), UR_COORD(a, i), + LL_COORD(b, i), UR_COORD(b, i))); if (d > distance) distance = d; } @@ -1333,7 +1339,7 @@ distance_chebyshev(PG_FUNCTION_ARGS) /* compute distance to zero for those dimensions in (a) absent in (b) */ for (i = DIM(b); i < DIM(a); i++) { - d = fabs(distance_1D(LL_COORD(a,i), UR_COORD(a,i), 0.0, 0.0)); + d = fabs(distance_1D(LL_COORD(a, i), UR_COORD(a, i), 0.0, 0.0)); if (d > distance) distance = d; } @@ -1357,44 +1363,41 @@ g_cube_distance(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - NDBOX *cube = DatumGetNDBOX(entry->key); - double retval; + NDBOX *cube = DatumGetNDBOX(entry->key); + double retval; if (strategy == CubeKNNDistanceCoord) { - int coord = PG_GETARG_INT32(1); + int coord = PG_GETARG_INT32(1); - if IS_POINT(cube) - { - retval = (cube)->x[(coord-1)%DIM(cube)]; - } + 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)] - ); - } + retval = Min(cube->x[(coord - 1) % DIM(cube)], + cube->x[(coord - 1) % DIM(cube) + DIM(cube)]); } else { - NDBOX *query = PG_GETARG_NDBOX(1); - switch(strategy) + NDBOX *query = PG_GETARG_NDBOX(1); + + switch (strategy) { - case CubeKNNDistanceTaxicab: - retval = DatumGetFloat8(DirectFunctionCall2(distance_taxicab, - PointerGetDatum(cube), PointerGetDatum(query))); - break; - case CubeKNNDistanceEuclid: - retval = DatumGetFloat8(DirectFunctionCall2(cube_distance, - PointerGetDatum(cube), PointerGetDatum(query))); - break; - case CubeKNNDistanceChebyshev: - retval = DatumGetFloat8(DirectFunctionCall2(distance_chebyshev, - PointerGetDatum(cube), PointerGetDatum(query))); - break; - default: - elog(ERROR, "Cube: unknown strategy number."); + case CubeKNNDistanceTaxicab: + retval = DatumGetFloat8(DirectFunctionCall2(distance_taxicab, + PointerGetDatum(cube), PointerGetDatum(query))); + break; + case CubeKNNDistanceEuclid: + retval = DatumGetFloat8(DirectFunctionCall2(cube_distance, + PointerGetDatum(cube), PointerGetDatum(query))); + break; + case CubeKNNDistanceChebyshev: + retval = DatumGetFloat8(DirectFunctionCall2(distance_chebyshev, + PointerGetDatum(cube), PointerGetDatum(query))); + break; + default: + elog(ERROR, "unrecognized cube strategy number: %d", strategy); + retval = 0; /* keep compiler quiet */ + break; } } PG_RETURN_FLOAT8(retval); @@ -1466,7 +1469,7 @@ Datum cube_ll_coord(PG_FUNCTION_ARGS) { NDBOX *c = PG_GETARG_NDBOX(0); - int n = PG_GETARG_INT16(1); + int n = PG_GETARG_INT32(1); double result; if (DIM(c) >= n && n > 0) @@ -1483,7 +1486,7 @@ Datum cube_ur_coord(PG_FUNCTION_ARGS) { NDBOX *c = PG_GETARG_NDBOX(0); - int n = PG_GETARG_INT16(1); + int n = PG_GETARG_INT32(1); double result; if (DIM(c) >= n && n > 0) @@ -1504,21 +1507,17 @@ Datum cube_coord(PG_FUNCTION_ARGS) { NDBOX *cube = PG_GETARG_NDBOX(0); - int coord = PG_GETARG_INT16(1); + int coord = PG_GETARG_INT32(1); - if ((coord > 0) && (coord <= 2*DIM(cube))) - { - if IS_POINT(cube) - PG_RETURN_FLOAT8( (cube)->x[(coord-1)%DIM(cube)] ); - else - PG_RETURN_FLOAT8( (cube)->x[coord-1] ); - } - else - { + if (coord <= 0 || coord > 2 * DIM(cube)) ereport(ERROR, - (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), - errmsg("Cube index out of bounds"))); - } + (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), + errmsg("cube index %d is out of bounds", coord))); + + if (IS_POINT(cube)) + PG_RETURN_FLOAT8(cube->x[(coord - 1) % DIM(cube)]); + else + PG_RETURN_FLOAT8(cube->x[coord - 1]); } @@ -1536,27 +1535,28 @@ Datum cube_coord_llur(PG_FUNCTION_ARGS) { NDBOX *cube = PG_GETARG_NDBOX(0); - int coord = PG_GETARG_INT16(1); + int coord = PG_GETARG_INT32(1); - if ((coord > 0) && (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 ((coord > DIM(cube)) && (coord <= 2*DIM(cube))) + 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)%DIM(cube)] ); + if (IS_POINT(cube)) + PG_RETURN_FLOAT8(cube->x[coord - 1]); else - PG_RETURN_FLOAT8( Max((cube)->x[coord-1], (cube)->x[coord-1-DIM(cube)]) ); + PG_RETURN_FLOAT8(Min(cube->x[coord - 1], + cube->x[coord - 1 + DIM(cube)])); } else { - ereport(ERROR, - (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), - errmsg("Cube index out of bounds"))); + 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)])); } } diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out index 769ad3a88de..e9e2c0f15b3 100644 --- a/contrib/cube/expected/cube.out +++ b/contrib/cube/expected/cube.out @@ -1458,13 +1458,13 @@ SELECT cube(array[10,20,30], array[40,50,60])->6; (1 row) SELECT cube(array[10,20,30], array[40,50,60])->0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->7; -ERROR: Cube index out of bounds +ERROR: cube index 7 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-1; -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds SELECT cube(array[10,20,30])->3; ?column? ---------- @@ -1478,7 +1478,7 @@ SELECT cube(array[10,20,30])->6; (1 row) SELECT cube(array[10,20,30])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds -- "normalized" coordinate access SELECT cube(array[10,20,30], array[40,50,60])~>1; ?column? @@ -1517,7 +1517,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>3; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[40,50,60], array[10,20,30])~>4; ?column? ---------- @@ -1525,7 +1525,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>4; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>(-1); -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds -- Load some example data and build the index -- CREATE TABLE test_cube (c cube); diff --git a/contrib/cube/expected/cube_1.out b/contrib/cube/expected/cube_1.out index 7178088e4ae..c40fabcd46e 100644 --- a/contrib/cube/expected/cube_1.out +++ b/contrib/cube/expected/cube_1.out @@ -1458,13 +1458,13 @@ SELECT cube(array[10,20,30], array[40,50,60])->6; (1 row) SELECT cube(array[10,20,30], array[40,50,60])->0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->7; -ERROR: Cube index out of bounds +ERROR: cube index 7 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-1; -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds SELECT cube(array[10,20,30])->3; ?column? ---------- @@ -1478,7 +1478,7 @@ SELECT cube(array[10,20,30])->6; (1 row) SELECT cube(array[10,20,30])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds -- "normalized" coordinate access SELECT cube(array[10,20,30], array[40,50,60])~>1; ?column? @@ -1517,7 +1517,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>3; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[40,50,60], array[10,20,30])~>4; ?column? ---------- @@ -1525,7 +1525,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>4; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>(-1); -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds -- Load some example data and build the index -- CREATE TABLE test_cube (c cube); diff --git a/contrib/cube/expected/cube_2.out b/contrib/cube/expected/cube_2.out index c2421c5805f..fef749c698f 100644 --- a/contrib/cube/expected/cube_2.out +++ b/contrib/cube/expected/cube_2.out @@ -1458,13 +1458,13 @@ SELECT cube(array[10,20,30], array[40,50,60])->6; (1 row) SELECT cube(array[10,20,30], array[40,50,60])->0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->7; -ERROR: Cube index out of bounds +ERROR: cube index 7 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-1; -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds SELECT cube(array[10,20,30])->3; ?column? ---------- @@ -1478,7 +1478,7 @@ SELECT cube(array[10,20,30])->6; (1 row) SELECT cube(array[10,20,30])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds -- "normalized" coordinate access SELECT cube(array[10,20,30], array[40,50,60])~>1; ?column? @@ -1517,7 +1517,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>3; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[40,50,60], array[10,20,30])~>4; ?column? ---------- @@ -1525,7 +1525,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>4; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>(-1); -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds -- Load some example data and build the index -- CREATE TABLE test_cube (c cube); diff --git a/contrib/cube/expected/cube_3.out b/contrib/cube/expected/cube_3.out index b6c961dcb96..31d2d1a64e0 100644 --- a/contrib/cube/expected/cube_3.out +++ b/contrib/cube/expected/cube_3.out @@ -1458,13 +1458,13 @@ SELECT cube(array[10,20,30], array[40,50,60])->6; (1 row) SELECT cube(array[10,20,30], array[40,50,60])->0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->7; -ERROR: Cube index out of bounds +ERROR: cube index 7 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-1; -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds SELECT cube(array[10,20,30], array[40,50,60])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds SELECT cube(array[10,20,30])->3; ?column? ---------- @@ -1478,7 +1478,7 @@ SELECT cube(array[10,20,30])->6; (1 row) SELECT cube(array[10,20,30])->-6; -ERROR: Cube index out of bounds +ERROR: cube index -6 is out of bounds -- "normalized" coordinate access SELECT cube(array[10,20,30], array[40,50,60])~>1; ?column? @@ -1517,7 +1517,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>3; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>0; -ERROR: Cube index out of bounds +ERROR: cube index 0 is out of bounds SELECT cube(array[40,50,60], array[10,20,30])~>4; ?column? ---------- @@ -1525,7 +1525,7 @@ SELECT cube(array[40,50,60], array[10,20,30])~>4; (1 row) SELECT cube(array[40,50,60], array[10,20,30])~>(-1); -ERROR: Cube index out of bounds +ERROR: cube index -1 is out of bounds -- Load some example data and build the index -- CREATE TABLE test_cube (c cube); diff --git a/doc/src/sgml/cube.sgml b/doc/src/sgml/cube.sgml index 666400800ce..4a093706e4a 100644 --- a/doc/src/sgml/cube.sgml +++ b/doc/src/sgml/cube.sgml @@ -75,8 +75,8 @@ entered in. The <type>cube</> functions automatically swap values if needed to create a uniform <quote>lower left — upper right</> internal representation. - When corners coincide cube stores only one corner along with a - special flag in order to reduce size wasted. + When the corners coincide, <type>cube</> stores only one corner + along with an <quote>is point</> flag to avoid wasting space. </para> <para> @@ -98,17 +98,17 @@ <title>Usage</title> <para> - The <filename>cube</> module includes a GiST index operator class for - <type>cube</> values. - The operators supported by the GiST operator class are shown in <xref linkend="cube-gist-operators">. + <xref linkend="cube-operators"> shows the operators provided for type + <type>cube</>. </para> - <table id="cube-gist-operators"> - <title>Cube GiST Operators</title> - <tgroup cols="2"> + <table id="cube-operators"> + <title>Cube Operators</title> + <tgroup cols="3"> <thead> <row> <entry>Operator</entry> + <entry>Result</entry> <entry>Description</entry> </row> </thead> @@ -116,160 +116,149 @@ <tbody> <row> <entry><literal>a = b</></entry> + <entry><type>boolean</></entry> <entry>The cubes a and b are identical.</entry> </row> <row> <entry><literal>a && b</></entry> + <entry><type>boolean</></entry> <entry>The cubes a and b overlap.</entry> </row> <row> <entry><literal>a @> b</></entry> + <entry><type>boolean</></entry> <entry>The cube a contains the cube b.</entry> </row> <row> <entry><literal>a <@ b</></entry> + <entry><type>boolean</></entry> <entry>The cube a is contained in the cube b.</entry> </row> <row> - <entry><literal>a -> n</></entry> - <entry>Get n-th coordinate of cube.</entry> + <entry><literal>a < b</></entry> + <entry><type>boolean</></entry> + <entry>The cube a is less than the cube b.</entry> </row> <row> - <entry><literal>a ~> n</></entry> - <entry> - Get n-th coordinate in 'normalized' cube representation. Noramlization - means coordinate rearrangement to form (lower left, upper right). - </entry> + <entry><literal>a <= b</></entry> + <entry><type>boolean</></entry> + <entry>The cube a is less than or equal to the cube b.</entry> </row> - </tbody> - </tgroup> - </table> - <para> - (Before PostgreSQL 8.2, the containment operators <literal>@></> and <literal><@</> were - respectively called <literal>@</> and <literal>~</>. These names are still available, but are - deprecated and will eventually be retired. Notice that the old names - are reversed from the convention formerly followed by the core geometric - data types!) - </para> + <row> + <entry><literal>a > b</></entry> + <entry><type>boolean</></entry> + <entry>The cube a is greater than the cube b.</entry> + </row> - <para> - GiST index can be used to retrieve nearest neighbours via several metric - operators. As always any of them can be used as ordinary function. - </para> + <row> + <entry><literal>a >= b</></entry> + <entry><type>boolean</></entry> + <entry>The cube a is greater than or equal to the cube b.</entry> + </row> - <table id="cube-gistknn-operators"> - <title>Cube GiST-kNN Operators</title> - <tgroup cols="2"> - <thead> <row> - <entry>Operator</entry> - <entry>Description</entry> + <entry><literal>a <> b</></entry> + <entry><type>boolean</></entry> + <entry>The cube a is not equal to the cube b.</entry> </row> - </thead> - <tbody> + + <row> + <entry><literal>a -> n</></entry> + <entry><type>float8</></entry> + <entry>Get <replaceable>n</>-th coordinate of cube (counting from 1).</entry> + </row> + + <row> + <entry><literal>a ~> n</></entry> + <entry><type>float8</></entry> + <entry> + Get <replaceable>n</>-th coordinate in <quote>normalized</> cube + representation, in which the coordinates have been rearranged into + the form <quote>lower left — upper right</>; that is, the + smaller endpoint along each dimension appears first. + </entry> + </row> + <row> <entry><literal>a <-> b</></entry> - <entry>Euclidean distance between a and b</entry> + <entry><type>float8</></entry> + <entry>Euclidean distance between a and b.</entry> </row> <row> <entry><literal>a <#> b</></entry> - <entry>Taxicab (L-1 metric) distance between a and b</entry> + <entry><type>float8</></entry> + <entry>Taxicab (L-1 metric) distance between a and b.</entry> </row> <row> <entry><literal>a <=> b</></entry> - <entry>Chebyshev (L-inf metric) distance between a and b</entry> + <entry><type>float8</></entry> + <entry>Chebyshev (L-inf metric) distance between a and b.</entry> </row> + </tbody> </tgroup> </table> <para> - Selection of nearing neigbours can be done in the following way: + (Before PostgreSQL 8.2, the containment operators <literal>@></> and <literal><@</> were + respectively called <literal>@</> and <literal>~</>. These names are still available, but are + deprecated and will eventually be retired. Notice that the old names + are reversed from the convention formerly followed by the core geometric + data types!) </para> -<programlisting> -SELECT c FROM test -ORDER BY cube(array[0.5,0.5,0.5])<->c -LIMIT 1; -</programlisting> - <para> - Also kNN framework allows us to cheat with metrics in order to get results - sorted by selected coodinate directly from the index without extra sorting - step. That technique significantly faster on small values of LIMIT, however - with bigger values of LIMIT planner will switch automatically to standart - index scan and sort. - That behavior can be achieved using coordinate operator - (cube c)~>(int offset). + The scalar ordering operators (<literal><</>, <literal>>=</>, etc) + do not make a lot of sense for any practical purpose but sorting. These + operators first compare the first coordinates, and if those are equal, + compare the second coordinates, etc. They exist mainly to support the + b-tree index operator class for <type>cube</>, which can be useful for + example if you would like a UNIQUE constraint on a <type>cube</> column. </para> -<programlisting> -=> select cube(array[0.41,0.42,0.43])~>2 as coord; - coord -------- - 0.42 -(1 row) -</programlisting> <para> - So using that operator as kNN metric we can obtain cubes sorted by it's - coordinate. + The <filename>cube</> module also provides a GiST index operator class for + <type>cube</> values. + A <type>cube</> GiST index can be used to search for values using the + <literal>=</>, <literal>&&</>, <literal>@></>, and + <literal><@</> operators in <literal>WHERE</> clauses. </para> + <para> - To get cubes ordered by first coordinate of lower left corner ascending - one can use the following query: - </para> + In addition, a <type>cube</> GiST index can be used to find nearest + neighbors using the metric operators + <literal><-></>, <literal><#></>, and + <literal><=></> in <literal>ORDER BY</> clauses. + For example, the nearest neighbor of the 3-D point (0.5, 0.5, 0.5) + could be found efficiently with: <programlisting> -SELECT c FROM test ORDER BY c~>1 LIMIT 5; +SELECT c FROM test +ORDER BY cube(array[0.5,0.5,0.5]) <-> c +LIMIT 1; </programlisting> - <para> - And to get cubes descending by first coordinate of upper right corner - of 2d-cube: </para> -<programlisting> -SELECT c FROM test ORDER BY c~>3 DESC LIMIT 5; -</programlisting> - - <para> - The standard B-tree operators are also provided, for example - - <informaltable> - <tgroup cols="2"> - <thead> - <row> - <entry>Operator</entry> - <entry>Description</entry> - </row> - </thead> - - <tbody> - <row> - <entry><literal>[a, b] < [c, d]</literal></entry> - <entry>Less than</entry> - </row> - - <row> - <entry><literal>[a, b] > [c, d]</literal></entry> - <entry>Greater than</entry> - </row> - </tbody> - </tgroup> - </informaltable> - - These operators do not make a lot of sense for any practical - purpose but sorting. These operators first compare (a) to (c), - and if these are equal, compare (b) to (d). That results in - reasonably good sorting in most cases, which is useful if - you want to use ORDER BY with this type. + The <literal>~></> operator can also be used in this way to + efficiently retrieve the first few values sorted by a selected coordinate. + For example, to get the first few cubes ordered by the first coordinate + (lower left corner) ascending one could use the following query: +<programlisting> +SELECT c FROM test ORDER BY c ~> 1 LIMIT 5; +</programlisting> + And to get 2-D cubes ordered by the first coordinate of the upper right + corner descending: +<programlisting> +SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5; +</programlisting> </para> <para> |