attached to the same message with the Earth Distance patches.
Recent changes include changing the subscript in one place I forgot
in the previous bugfix patch. A couple of added regression tests, which
should help catch this mistake if it reappears.
I also put in a limit of 100 dimensions in cube_large and cube_in to
prevent making it easy to create very large cubes. Changing one define
in cubedata.h will raise the limit if some needs more dimensions.
Bruno Wolff III
-Changes that were made in August 2002.
+Changes that were made in August/September 2002 by Bruno Wolff III.
Note that this was based on a 7.3 development version and changes may not
directly work with earlier versions.
before a decimal point from being accepted. This was submitted as a separate
patch and may already be applied.
-I reported but did not fix a potential buffer overrun problem in cube_yyerror
-in cubeparse.y.
-
cube_inter should really return NULL if the two cubes don't overlap. However
this requires changing to the new calling sequence and I don't know enough
about how to do it to make the change.
same thing with the overhead of a function call and memory allocation.
I added memset calls to zero out newly allocated NDBOXes as the documentation
-on functions indicates should be done.
+on functions indicates should be done. This still doesn't allow a hash
+index for equality since there are multiple representations of the
+same cube.
I got rid of a call to cube_same in cube_lt and cube_gt since the test
was redundant with other checks being made. The call to cube_same would
I added documentation for cube_distance and the new functions to README.cube
as well as making a few other minor changes.
+I changed create function to create or replace function in the install
+script.
+
+I limited the number of dimensions allowed in cube_enlarge and cube_in
+to 100 to make it harder for people to mess up the database. The constant
+is defined in cubedata.h and can be increased if you need something larger.
+
+I added grant statements to the install script to make the functions
+executable to everyone.
+
Bruno Wolff III
postgres binaries in the PATH.
This only installs the type implementation and documentation. To make the
-type available in any particular database, do
+type available in any particular database, as a postgres superuser do:
psql -d databasename < cube.sql
test code is a direct adaptation of the regression tests from the main
source tree).
+By default the external functions are made executable by anyone.
SYNTAX
======
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.
+ 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.
There are a few other potentially useful functions defined in cube.c
that vanished from the schema because I stopped using them. Some of
------------------------------------------------------------------------
Minor updates to this package were made by Bruno Wolff III
-in August of 2002.
+in August/September of 2002.
These include changing the precision from single precision to double
precision and adding some new functions.
bool cube_lt(NDBOX * a, NDBOX * b);
bool cube_gt(NDBOX * a, NDBOX * b);
double *cube_distance(NDBOX * a, NDBOX * b);
-int cube_dim(NDBOX * a);
-double *cube_ll_coord(NDBOX * a, int n);
-double *cube_ur_coord(NDBOX * a, int n);
+int4 cube_dim(NDBOX * a);
+double *cube_ll_coord(NDBOX * a, int4 n);
+double *cube_ur_coord(NDBOX * a, int4 n);
bool cube_is_point(NDBOX * a);
-NDBOX *cube_enlarge(NDBOX * a, double *r, int n);
+NDBOX *cube_enlarge(NDBOX * a, double *r, int4 n);
/*
}
/* Return dimensions in use in the data structure */
-int
+int4
cube_dim(NDBOX * a)
{
/* Other things will break before unsigned int doesn't fit. */
/* Return a specific normalized LL coordinate */
double *
-cube_ll_coord(NDBOX * a, int n)
+cube_ll_coord(NDBOX * a, int4 n)
{
double *result;
/* Return a specific normalized UR coordinate */
double *
-cube_ur_coord(NDBOX * a, int n)
+cube_ur_coord(NDBOX * a, int4 n)
{
double *result;
/* Increase or decrease box size by a radius in at least n dimensions. */
NDBOX *
-cube_enlarge(NDBOX * a, double *r, int n)
+cube_enlarge(NDBOX * a, double *r, int4 n)
{
NDBOX *result;
int dim = 0;
int size;
int i,
- j;
+ j,
+ k;
+ if (n > CUBE_MAX_DIM) n = CUBE_MAX_DIM;
if (*r > 0 && n > 0)
dim = n;
if (a->dim > dim)
memset(result, 0, size);
result->size = size;
result->dim = dim;
- for (i = 0, j = dim; i < a->dim; i++, j++)
+ for (i = 0, j = dim, k = a->dim; i < a->dim; i++, j++, k++)
{
- if (a->x[i] >= a->x[j])
+ if (a->x[i] >= a->x[k])
{
- result->x[i] = a->x[j] - *r;
+ result->x[i] = a->x[k] - *r;
result->x[j] = a->x[i] + *r;
}
else
{
result->x[i] = a->x[i] - *r;
- result->x[j] = a->x[j] + *r;
+ result->x[j] = a->x[k] + *r;
}
if (result->x[i] > result->x[j])
{
-- Create the user-defined type for N-dimensional boxes
--
-BEGIN TRANSACTION;
+BEGIN;
-- Adjust this setting to control where the objects get created.
SET search_path = public;
-CREATE FUNCTION cube_in(cstring)
+CREATE OR REPLACE FUNCTION cube_in(cstring)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE 'c'IMMUTABLE STRICT;
-CREATE FUNCTION cube_out(cube)
+CREATE OR REPLACE FUNCTION cube_out(cube)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'c'IMMUTABLE STRICT;
-- Convert from text to cube
-CREATE FUNCTION cube(text)
-RETURNS cube
+CREATE OR REPLACE FUNCTION cube(text) RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE 'c' IMMUTABLE STRICT;
-- Left/Right methods
-CREATE FUNCTION cube_over_left(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_over_left(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_over_left(cube, cube) IS
'is over and left of (NOT IMPLEMENTED)';
-CREATE FUNCTION cube_over_right(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_over_right(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_over_right(cube, cube) IS
'is over and right of (NOT IMPLEMENTED)';
-CREATE FUNCTION cube_left(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_left(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_left(cube, cube) IS
'is left of (NOT IMPLEMENTED)';
-CREATE FUNCTION cube_right(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_right(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_right(cube, cube) IS
-- Comparison methods
-CREATE FUNCTION cube_lt(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_lt(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_lt(cube, cube) IS
'lower than';
-CREATE FUNCTION cube_gt(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_gt(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_gt(cube, cube) IS
'greater than';
-CREATE FUNCTION cube_contains(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_contains(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_contains(cube, cube) IS
'contains';
-CREATE FUNCTION cube_contained(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_contained(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_contained(cube, cube) IS
'contained in';
-CREATE FUNCTION cube_overlap(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_overlap(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_overlap(cube, cube) IS
'overlaps';
-CREATE FUNCTION cube_same(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_same(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_same(cube, cube) IS
'same as';
-CREATE FUNCTION cube_different(cube, cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_different(cube, cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_different(cube, cube) IS
-- support routines for indexing
-CREATE FUNCTION cube_union(cube, cube) RETURNS cube
+CREATE OR REPLACE FUNCTION cube_union(cube, cube) RETURNS cube
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-CREATE FUNCTION cube_inter(cube, cube) RETURNS cube
+CREATE OR REPLACE FUNCTION cube_inter(cube, cube) RETURNS cube
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-CREATE FUNCTION cube_size(cube) RETURNS float8
+CREATE OR REPLACE FUNCTION cube_size(cube) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-- proximity routines
-CREATE FUNCTION cube_distance(cube, cube) RETURNS float8
+CREATE OR REPLACE FUNCTION cube_distance(cube, cube) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-- Extracting elements functions
-CREATE FUNCTION cube_dim(cube) RETURNS int4
+CREATE OR REPLACE FUNCTION cube_dim(cube) RETURNS int4
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-CREATE FUNCTION cube_ll_coord(cube, int4) RETURNS float8
+CREATE OR REPLACE FUNCTION cube_ll_coord(cube, int4) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-CREATE FUNCTION cube_ur_coord(cube, int4) RETURNS float8
+CREATE OR REPLACE FUNCTION cube_ur_coord(cube, int4) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-- Test if cube is also a point
-CREATE FUNCTION cube_is_point(cube) RETURNS bool
+CREATE OR REPLACE FUNCTION cube_is_point(cube) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-- Increasing the size of a cube by a radius in at least n dimensions
-CREATE FUNCTION cube_enlarge(cube, float8, int4) RETURNS cube
+CREATE OR REPLACE FUNCTION cube_enlarge(cube, float8, int4) RETURNS cube
AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
--
-- define the GiST support methods
-CREATE FUNCTION g_cube_consistent(internal,cube,int4) RETURNS bool
+CREATE OR REPLACE FUNCTION g_cube_consistent(internal,cube,int4) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE 'c';
-CREATE FUNCTION g_cube_compress(internal) RETURNS internal
+CREATE OR REPLACE FUNCTION g_cube_compress(internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c';
-CREATE FUNCTION g_cube_decompress(internal) RETURNS internal
+CREATE OR REPLACE FUNCTION g_cube_decompress(internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c';
-CREATE FUNCTION g_cube_penalty(internal,internal,internal) RETURNS internal
+CREATE OR REPLACE FUNCTION g_cube_penalty(internal,internal,internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c' STRICT;
-CREATE FUNCTION g_cube_picksplit(internal, internal) RETURNS internal
+CREATE OR REPLACE FUNCTION g_cube_picksplit(internal, internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c';
-CREATE FUNCTION g_cube_union(bytea, internal) RETURNS cube
+CREATE OR REPLACE FUNCTION g_cube_union(bytea, internal) RETURNS cube
AS 'MODULE_PATHNAME' LANGUAGE 'c';
-CREATE FUNCTION g_cube_same(cube, cube, internal) RETURNS internal
+CREATE OR REPLACE FUNCTION g_cube_same(cube, cube, internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c';
FUNCTION 6 g_cube_picksplit (internal, internal),
FUNCTION 7 g_cube_same (cube, cube, internal);
+--
+-- By default the externally visible functions are made executable by
+-- anyone. To restrict their access comment out the following grant commands.
+--
-END TRANSACTION;
+GRANT EXECUTE ON FUNCTION cube(text) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_over_left(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_over_right(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_left(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_right(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_lt(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_gt(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_contains(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_contained(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_overlap(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_same(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_different(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_union(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_inter(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_size(cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_distance(cube, cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_dim(cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_ll_coord(cube, int4) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_ur_coord(cube, int4) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_is_point(cube) TO PUBLIC;
+GRANT EXECUTE ON FUNCTION cube_enlarge(cube, float8, int4) TO PUBLIC;
+
+COMMIT;
+#define CUBE_MAX_DIM (100)
typedef struct NDBOX
{
unsigned int size; /* required to be a Postgres varlena type */
static int delim_count(char *s, char delim);
static NDBOX * write_box(unsigned int dim, char *str1, char *str2);
-static NDBOX * write_point_as_box(char *s);
+static NDBOX * write_point_as_box(char *s, int dim);
%}
elog(ERROR, "(1) bad cube representation; different point dimensions in (%s) and (%s)\n", $2, $4);
YYABORT;
}
+ if (dim > CUBE_MAX_DIM) {
+ reset_parse_buffer();
+ elog(ERROR, "(8) bad cube representation; more than %d dimensions\n", CUBE_MAX_DIM);
+ YYABORT;
+ }
*((void **)result) = write_box( dim, $2, $4 );
elog(ERROR, "(3) bad cube representation; different point dimensions in (%s) and (%s)\n", $1, $3);
YYABORT;
}
+ if (dim > CUBE_MAX_DIM) {
+ reset_parse_buffer();
+ elog(ERROR, "(8) bad cube representation; more than %d dimensions\n", CUBE_MAX_DIM);
+ YYABORT;
+ }
*((void **)result) = write_box( dim, $1, $3 );
}
|
paren_list {
+ int dim;
int c = parse_buffer_curr_char();
int pos = parse_buffer_pos();
YYABORT;
}
- *((void **)result) = write_point_as_box($1);
+ dim = delim_count($1, ',') + 1;
+ if (dim > CUBE_MAX_DIM) {
+ reset_parse_buffer();
+ elog(ERROR, "(8) bad cube representation; more than %d dimensions\n", CUBE_MAX_DIM);
+ YYABORT;
+ }
+
+ *((void **)result) = write_point_as_box($1, dim);
}
|
list {
+ int dim;
int c = parse_buffer_curr_char();
int pos = parse_buffer_pos();
YYABORT;
}
- *((void **)result) = write_point_as_box($1);
+ dim = delim_count($1, ',') + 1;
+ if (dim > CUBE_MAX_DIM) {
+ reset_parse_buffer();
+ elog(ERROR, "(8) bad cube representation; more than %d dimensions\n", CUBE_MAX_DIM);
+ YYABORT;
+ }
+ *((void **)result) = write_point_as_box($1, dim);
}
;
}
-static NDBOX * write_point_as_box(char *str)
+static NDBOX * write_point_as_box(char *str, int dim)
{
NDBOX * bp;
int i, size;
double x;
- int dim = delim_count(str, ',') + 1;
char * s = str;
size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
SELECT '1..2'::cube AS cube; -- 7
ERROR: (7) bad cube representation; garbage at or before char 4, ('end of input', \000)
+--
+-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
+--
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+ERROR: (8) bad cube representation; more than 100 dimensions
+
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+ERROR: (8) bad cube representation; more than 100 dimensions
+
--
-- testing the operators
--
(0)
(1 row)
+SELECT cube_enlarge('(2),(-2)'::cube, 0, 4);
+ cube_enlarge
+--------------
+ (-2),(2)
+(1 row)
+
SELECT cube_enlarge('(0)'::cube, 1, 0);
cube_enlarge
--------------
(-1, -1),(1, 1)
(1 row)
+SELECT cube_enlarge('(2),(-2)'::cube, 1, 4);
+ cube_enlarge
+-------------------------------
+ (-3, -1, -1, -1),(3, 1, 1, 1)
+(1 row)
+
SELECT cube_enlarge('(0)'::cube, -1, 0);
cube_enlarge
--------------
(0)
(1 row)
+SELECT cube_enlarge('(2),(-2)'::cube, -1, 4);
+ cube_enlarge
+--------------
+ (-1),(1)
+(1 row)
+
SELECT cube_enlarge('(0,0,0)'::cube, 1, 0);
cube_enlarge
------------------------
SELECT '1,2a'::cube AS cube; -- 7
SELECT '1..2'::cube AS cube; -- 7
+--
+-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
+--
+
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+
--
-- testing the operators
--
SELECT cube_enlarge('(0)'::cube, 0, 0);
SELECT cube_enlarge('(0)'::cube, 0, 1);
SELECT cube_enlarge('(0)'::cube, 0, 2);
+SELECT cube_enlarge('(2),(-2)'::cube, 0, 4);
SELECT cube_enlarge('(0)'::cube, 1, 0);
SELECT cube_enlarge('(0)'::cube, 1, 1);
SELECT cube_enlarge('(0)'::cube, 1, 2);
+SELECT cube_enlarge('(2),(-2)'::cube, 1, 4);
SELECT cube_enlarge('(0)'::cube, -1, 0);
SELECT cube_enlarge('(0)'::cube, -1, 1);
SELECT cube_enlarge('(0)'::cube, -1, 2);
+SELECT cube_enlarge('(2),(-2)'::cube, -1, 4);
SELECT cube_enlarge('(0,0,0)'::cube, 1, 0);
SELECT cube_enlarge('(0,0,0)'::cube, 1, 2);
SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 1, 2);