mirror of
https://github.com/postgres/postgres.git
synced 2025-05-30 00:02:11 -04:00
530 lines
15 KiB
Plaintext
530 lines
15 KiB
Plaintext
|
|
<sect1 id="cube">
|
|
<title>cube</title>
|
|
|
|
<indexterm zone="cube">
|
|
<primary>cube</primary>
|
|
</indexterm>
|
|
|
|
<para>
|
|
This module contains the user-defined type, CUBE, representing
|
|
multidimensional cubes.
|
|
</para>
|
|
|
|
<sect2>
|
|
<title>Syntax</title>
|
|
|
|
<para>
|
|
The following are valid external representations for the CUBE type:
|
|
</para>
|
|
|
|
<table>
|
|
<title>Cube external representations</title>
|
|
<tgroup cols="2">
|
|
<tbody>
|
|
<row>
|
|
<entry>'x'</entry>
|
|
<entry>A floating point value representing a one-dimensional point or
|
|
one-dimensional zero length cubement
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x)'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'x1,x2,x3,...,xn'</entry>
|
|
<entry>A point in n-dimensional space, represented internally as a zero
|
|
volume box
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x1,x2,x3,...,xn)'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x),(y)'</entry>
|
|
<entry>1-D cubement starting at x and ending at y or vice versa; the
|
|
order does not matter
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x1,...,xn),(y1,...,yn)'</entry>
|
|
<entry>n-dimensional box represented by a pair of its opposite corners, no
|
|
matter which. Functions take care of swapping to achieve "lower left --
|
|
upper right" representation before computing any values
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Grammar</title>
|
|
<table>
|
|
<title>Cube Grammar Rules</title>
|
|
<tgroup cols="2">
|
|
<tbody>
|
|
<row>
|
|
<entry>rule 1</entry>
|
|
<entry>box -> O_BRACKET paren_list COMMA paren_list C_BRACKET</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 2</entry>
|
|
<entry>box -> paren_list COMMA paren_list</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 3</entry>
|
|
<entry>box -> paren_list</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 4</entry>
|
|
<entry>box -> list</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 5</entry>
|
|
<entry>paren_list -> O_PAREN list C_PAREN</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 6</entry>
|
|
<entry>list -> FLOAT</entry>
|
|
</row>
|
|
<row>
|
|
<entry>rule 7</entry>
|
|
<entry>list -> list COMMA FLOAT</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Tokens</title>
|
|
<table>
|
|
<title>Cube Grammar Rules</title>
|
|
<tgroup cols="2">
|
|
<tbody>
|
|
<row>
|
|
<entry>n</entry>
|
|
<entry>[0-9]+</entry>
|
|
</row>
|
|
<row>
|
|
<entry>i</entry>
|
|
<entry>nteger [+-]?{n}</entry>
|
|
</row>
|
|
<row>
|
|
<entry>real</entry>
|
|
<entry>[+-]?({n}\.{n}?|\.{n})</entry>
|
|
</row>
|
|
<row>
|
|
<entry>FLOAT</entry>
|
|
<entry>({integer}|{real})([eE]{integer})?</entry>
|
|
</row>
|
|
<row>
|
|
<entry>O_BRACKET</entry>
|
|
<entry>\[</entry>
|
|
</row>
|
|
<row>
|
|
<entry>C_BRACKET</entry>
|
|
<entry>\]</entry>
|
|
</row>
|
|
<row>
|
|
<entry>O_PAREN</entry>
|
|
<entry>\(</entry>
|
|
</row>
|
|
<row>
|
|
<entry>C_PAREN</entry>
|
|
<entry>\)</entry>
|
|
</row>
|
|
<row>
|
|
<entry>COMMA</entry>
|
|
<entry>\,</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Examples</title>
|
|
<table>
|
|
<title>Examples</title>
|
|
<tgroup cols="2">
|
|
<tbody>
|
|
<row>
|
|
<entry>'x'</entry>
|
|
<entry>A floating point value representing a one-dimensional point
|
|
(or, zero-length one-dimensional interval)
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x)'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'x1,x2,x3,...,xn'</entry>
|
|
<entry>A point in n-dimensional space,represented internally as a zero
|
|
volume cube
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x1,x2,x3,...,xn)'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x),(y)'</entry>
|
|
<entry>A 1-D interval starting at x and ending at y or vice versa; the
|
|
order does not matter
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'[(x),(y)]'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'(x1,...,xn),(y1,...,yn)'</entry>
|
|
<entry>An n-dimensional box represented by a pair of its diagonally
|
|
opposite corners, regardless of order. Swapping is provided
|
|
by all comarison routines to ensure the
|
|
"lower left -- upper right" representation
|
|
before actaul comparison takes place.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>'[(x1,...,xn),(y1,...,yn)]'</entry>
|
|
<entry>Same as above</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
<para>
|
|
White space is ignored, so '[(x),(y)]' can be: '[ ( x ), ( y ) ]'
|
|
</para>
|
|
</sect2>
|
|
<sect2>
|
|
<title>Defaults</title>
|
|
<para>
|
|
I believe this union:
|
|
</para>
|
|
<programlisting>
|
|
select cube_union('(0,5,2),(2,3,1)','0');
|
|
cube_union
|
|
-------------------
|
|
(0, 0, 0),(2, 5, 2)
|
|
(1 row)
|
|
</programlisting>
|
|
|
|
<para>
|
|
does not contradict to the common sense, neither does the intersection
|
|
</para>
|
|
|
|
<programlisting>
|
|
select cube_inter('(0,-1),(1,1)','(-2),(2)');
|
|
cube_inter
|
|
-------------
|
|
(0, 0),(1, 0)
|
|
(1 row)
|
|
</programlisting>
|
|
|
|
<para>
|
|
In all binary operations on differently sized boxes, I assume the smaller
|
|
one to be a cartesian projection, i. e., having zeroes in place of coordinates
|
|
omitted in the string representation. The above examples are equivalent to:
|
|
</para>
|
|
|
|
<programlisting>
|
|
cube_union('(0,5,2),(2,3,1)','(0,0,0),(0,0,0)');
|
|
cube_inter('(0,-1),(1,1)','(-2,0),(2,0)');
|
|
</programlisting>
|
|
|
|
<para>
|
|
The following containment predicate uses the point syntax,
|
|
while in fact the second argument is internally represented by a box.
|
|
This syntax makes it unnecessary to define the special Point type
|
|
and functions for (box,point) predicates.
|
|
</para>
|
|
|
|
<programlisting>
|
|
select cube_contains('(0,0),(1,1)', '0.5,0.5');
|
|
cube_contains
|
|
--------------
|
|
t
|
|
(1 row)
|
|
</programlisting>
|
|
</sect2>
|
|
<sect2>
|
|
<title>Precision</title>
|
|
<para>
|
|
Values are stored internally as 64-bit floating point numbers. This means that
|
|
numbers with more than about 16 significant digits will be truncated.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Usage</title>
|
|
<para>
|
|
The access method for CUBE is a GiST index (gist_cube_ops), which is a
|
|
generalization of R-tree. GiSTs allow the postgres implementation of
|
|
R-tree, originally encoded to support 2-D geometric types such as
|
|
boxes and polygons, to be used with any data type whose data domain
|
|
can be partitioned using the concepts of containment, intersection and
|
|
equality. In other words, everything that can intersect or contain
|
|
its own kind can be indexed with a GiST. That includes, among other
|
|
things, all geometric data types, regardless of their dimensionality
|
|
(see also contrib/seg).
|
|
</para>
|
|
|
|
<para>
|
|
The operators supported by the GiST access method include:
|
|
</para>
|
|
|
|
<programlisting>
|
|
a = b Same as
|
|
</programlisting>
|
|
<para>
|
|
The cubements a and b are identical.
|
|
</para>
|
|
|
|
<programlisting>
|
|
a && b Overlaps
|
|
</programlisting>
|
|
<para>
|
|
The cubements a and b overlap.
|
|
</para>
|
|
|
|
<programlisting>
|
|
a @> b Contains
|
|
</programlisting>
|
|
<para>
|
|
The cubement a contains the cubement b.
|
|
</para>
|
|
|
|
<programlisting>
|
|
a <@ b Contained in
|
|
</programlisting>
|
|
<para>
|
|
The cubement a is contained in b.
|
|
</para>
|
|
|
|
<para>
|
|
(Before PostgreSQL 8.2, the containment operators @> and <@ were
|
|
respectively called @ and ~. 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
|
|
datatypes!)
|
|
</para>
|
|
|
|
<para>
|
|
Although the mnemonics of the following operators is questionable, I
|
|
preserved them to maintain visual consistency with other geometric
|
|
data types defined in Postgres.
|
|
</para>
|
|
|
|
<para>
|
|
Other operators:
|
|
</para>
|
|
|
|
<programlisting>
|
|
[a, b] < [c, d] Less than
|
|
[a, b] > [c, d] Greater than
|
|
</programlisting>
|
|
|
|
<para>
|
|
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 accounts for
|
|
reasonably good sorting in most cases, which is useful if
|
|
you want to use ORDER BY with this type
|
|
</para>
|
|
|
|
<para>
|
|
The following functions are available:
|
|
</para>
|
|
|
|
<table>
|
|
<title>Functions available</title>
|
|
<tgroup cols="2">
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>cube_distance(cube, cube) returns double</literal></entry>
|
|
<entry>cube_distance returns the distance between two cubes. If both
|
|
cubes are points, this is the normal distance function.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry><literal>cube(float8) returns cube</literal></entry>
|
|
<entry>This makes a one dimensional cube with both coordinates the same.
|
|
If the type of the argument is a numeric type other than float8 an
|
|
explicit cast to float8 may be needed.
|
|
<literal>cube(1) == '(1)'</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube(float8, float8) returns cube</literal></entry>
|
|
<entry>
|
|
This makes a one dimensional cube.
|
|
<literal>cube(1,2) == '(1),(2)'</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube(float8[]) returns cube</literal></entry>
|
|
<entry>This makes a zero-volume cube using the coordinates
|
|
defined by thearray.<literal>cube(ARRAY[1,2]) == '(1,2)'</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube(float8[], float8[]) returns cube</literal></entry>
|
|
<entry>This makes a cube, with upper right and lower left
|
|
coordinates as defined by the 2 float arrays. Arrays must be of the
|
|
same length.
|
|
<literal>cube('{1,2}'::float[], '{3,4}'::float[]) == '(1,2),(3,4)'
|
|
</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube(cube, float8) returns cube</literal></entry>
|
|
<entry>This builds a new cube by adding a dimension on to an
|
|
existing cube with the same values for both parts of the new coordinate.
|
|
This is useful for building cubes piece by piece from calculated values.
|
|
<literal>cube('(1)',2) == '(1,2),(1,2)'</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube(cube, float8, float8) returns cube</literal></entry>
|
|
<entry>This builds a new cube by adding a dimension on to an
|
|
existing cube. This is useful for building cubes piece by piece from
|
|
calculated values. <literal>cube('(1,2)',3,4) == '(1,3),(2,4)'</literal>
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_dim(cube) returns int</literal></entry>
|
|
<entry>cube_dim returns the number of dimensions stored in the
|
|
the data structure
|
|
for a cube. This is useful for constraints on the dimensions of a cube.
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_ll_coord(cube, int) returns double </literal></entry>
|
|
<entry>
|
|
cube_ll_coord returns the nth coordinate value for the lower left
|
|
corner of a cube. This is useful for doing coordinate transformations.
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_ur_coord(cube, int) returns double
|
|
</literal></entry>
|
|
<entry>cube_ur_coord returns the nth coordinate value for the
|
|
upper right corner of a cube. This is useful for doing coordinate
|
|
transformations.
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_subset(cube, int[]) returns cube
|
|
</literal></entry>
|
|
<entry>Builds a new cube from an existing cube, using a list of
|
|
dimension indexes
|
|
from an array. Can be used to find both the ll and ur coordinate of single
|
|
dimenion, e.g.: cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) = '(3),(7)'
|
|
Or can be used to drop dimensions, or reorder them as desired, e.g.:
|
|
cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) =
|
|
'(5, 3, 1, 1),(8, 7, 6, 6)'
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_is_point(cube) returns bool</literal></entry>
|
|
<entry>cube_is_point returns true if a cube is also a point.
|
|
This is true when the two defining corners are the same.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>cube_enlarge(cube, double, int) returns cube</literal></entry>
|
|
<entry>
|
|
cube_enlarge increases the size of a cube by a specified
|
|
radius in at least
|
|
n dimensions. If the radius is negative the box is shrunk instead. This
|
|
is useful for creating bounding boxes around a point for searching for
|
|
nearby points. All defined dimensions are changed by the radius. If n
|
|
is greater than the number of defined dimensions and the cube is being
|
|
increased (r >= 0) then 0 is used as the base for the extra coordinates.
|
|
LL coordinates are decreased by r and UR coordinates are increased by r.
|
|
If a LL coordinate is increased to larger than the corresponding UR
|
|
coordinate (this can only happen when r < 0) than both coordinates are
|
|
set to their average. To make it harder for people to break things there
|
|
is an effective maximum on the dimension of cubes of 100. This is set
|
|
in cubedata.h if you need something bigger.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>
|
|
There are a few other potentially useful functions defined in cube.c
|
|
that vanished from the schema because I stopped using them. Some of
|
|
these were meant to support type casting. Let me know if I was wrong:
|
|
I will then add them back to the schema. I would also appreciate
|
|
other ideas that would enhance the type and make it more useful.
|
|
</para>
|
|
|
|
<para>
|
|
For examples of usage, see sql/cube.sql
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Credits</title>
|
|
<para>
|
|
This code is essentially based on the example written for
|
|
Illustra, <ulink url="http://garcia.me.berkeley.edu/~adong/rtree"></ulink>
|
|
</para>
|
|
<para>
|
|
My thanks are primarily to Prof. Joe Hellerstein
|
|
(<ulink url="http://db.cs.berkeley.edu/~jmh/"></ulink>) for elucidating the
|
|
gist of the GiST (<ulink url="http://gist.cs.berkeley.edu/"></ulink>), and
|
|
to his former student, Andy Dong
|
|
(<ulink url="http://best.me.berkeley.edu/~adong/"></ulink>), for his exemplar.
|
|
I am also grateful to all postgres developers, present and past, for enabling
|
|
myself to create my own world and live undisturbed in it. And I would like to
|
|
acknowledge my gratitude to Argonne Lab and to the U.S. Department of Energy
|
|
for the years of faithful support of my database research.
|
|
</para>
|
|
|
|
<para>
|
|
Gene Selkov, Jr.
|
|
Computational Scientist
|
|
Mathematics and Computer Science Division
|
|
Argonne National Laboratory
|
|
9700 S Cass Ave.
|
|
Building 221
|
|
Argonne, IL 60439-4844
|
|
<email>selkovjr@mcs.anl.gov</email>
|
|
</para>
|
|
|
|
<para>
|
|
Minor updates to this package were made by Bruno Wolff III
|
|
<email>bruno@wolff.to</email> in August/September of 2002. These include
|
|
changing the precision from single precision to double precision and adding
|
|
some new functions.
|
|
</para>
|
|
|
|
<para>
|
|
Additional updates were made by Joshua Reich <email>josh@root.net</email> in
|
|
July 2006. These include <literal>cube(float8[], float8[])</literal> and
|
|
cleaning up the code to use the V1 call protocol instead of the deprecated V0
|
|
form.
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|