diff --git a/contrib/cube/README.cube b/contrib/cube/README.cube index 93ba63dd78..42b84fb061 100644 --- a/contrib/cube/README.cube +++ b/contrib/cube/README.cube @@ -264,6 +264,27 @@ cube(text) returns cube cube takes text input and returns a cube. This is useful for making cubes from computed strings. +cube(float8) returns cube + 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. + cube(1) == '(1)' + +cube(float8, float8) returns cube + This makes a one dimensional cube. + cube(1,2) == '(1),(2)' + +cube(cube, float8) returns cube + 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. + cube('(1)',2) == '(1,2),(1,2)' + +cube(cube, float8, float8) returns cube + 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. + cube('(1,2)',3,4) == '(1,3),(2,4)' + cube_dim(cube) returns int 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. diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index d24d0f5593..b46eb35d3c 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -30,6 +30,13 @@ extern int cube_yyparse(); NDBOX *cube_in(char *str); NDBOX *cube(text *str); char *cube_out(NDBOX * cube); +NDBOX *cube_f8(double *); +NDBOX *cube_f8_f8(double *, double *); +NDBOX *cube_c_f8(NDBOX *, double *); +NDBOX *cube_c_f8_f8(NDBOX *, double *, double *); +int4 cube_dim(NDBOX * a); +double *cube_ll_coord(NDBOX * a, int4 n); +double *cube_ur_coord(NDBOX * a, int4 n); /* @@ -73,9 +80,6 @@ bool cube_right(NDBOX * a, NDBOX * b); bool cube_lt(NDBOX * a, NDBOX * b); bool cube_gt(NDBOX * a, NDBOX * b); double *cube_distance(NDBOX * a, NDBOX * b); -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, int4 n); @@ -1226,3 +1230,78 @@ cube_enlarge(NDBOX * a, double *r, int4 n) } return result; } + +/* Create a one dimensional box with identical upper and lower coordinates */ +NDBOX * +cube_f8(double *x1) +{ + NDBOX *result; + int size; + size = offsetof(NDBOX, x[0]) + sizeof(double) * 2; + result = (NDBOX *) palloc(size); + memset(result, 0, size); + result->size = size; + result->dim = 1; + result->x[0] = *x1; + result->x[1] = *x1; + return result; +} + +/* Create a one dimensional box */ +NDBOX * +cube_f8_f8(double *x1, double *x2) +{ + NDBOX *result; + int size; + size = offsetof(NDBOX, x[0]) + sizeof(double) * 2; + result = (NDBOX *) palloc(size); + memset(result, 0, size); + result->size = size; + result->dim = 1; + result->x[0] = *x1; + result->x[1] = *x2; + return result; +} + +/* Add a dimension to an existing cube with the same values for the new + coordinate */ +NDBOX * +cube_c_f8(NDBOX *c, double *x1) +{ + NDBOX *result; + int size; + int i; + size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) * 2; + result = (NDBOX *) palloc(size); + memset(result, 0, size); + result->size = size; + result->dim = c->dim + 1; + for (i = 0; i < c->dim; i++) { + result->x[i] = c->x[i]; + result->x[result->dim + i] = c->x[c->dim + i]; + } + result->x[result->dim - 1] = *x1; + result->x[2 * result->dim - 1] = *x1; + return result; +} + +/* Add a dimension to an existing cube */ +NDBOX * +cube_c_f8_f8(NDBOX *c, double *x1, double *x2) +{ + NDBOX *result; + int size; + int i; + size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) * 2; + result = (NDBOX *) palloc(size); + memset(result, 0, size); + result->size = size; + result->dim = c->dim + 1; + for (i = 0; i < c->dim; i++) { + result->x[i] = c->x[i]; + result->x[result->dim + i] = c->x[c->dim + i]; + } + result->x[result->dim - 1] = *x1; + result->x[2 * result->dim - 1] = *x2; + return result; +} diff --git a/contrib/cube/cube.sql.in b/contrib/cube/cube.sql.in index 60ac7d8aee..e79eb5263c 100644 --- a/contrib/cube/cube.sql.in +++ b/contrib/cube/cube.sql.in @@ -165,6 +165,22 @@ RETURNS float8 AS 'MODULE_PATHNAME' LANGUAGE 'C' IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cube(float8) RETURNS cube +AS 'MODULE_PATHNAME', 'cube_f8' +LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION cube(float8, float8) RETURNS cube +AS 'MODULE_PATHNAME', 'cube_f8_f8' +LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION cube(cube, float8) RETURNS cube +AS 'MODULE_PATHNAME', 'cube_c_f8' +LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION cube(cube, float8, float8) RETURNS cube +AS 'MODULE_PATHNAME', 'cube_c_f8_f8' +LANGUAGE 'C' IMMUTABLE STRICT; + -- Test if cube is also a point CREATE OR REPLACE FUNCTION cube_is_point(cube) diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out index beced4e64a..3a1e670d66 100644 --- a/contrib/cube/expected/cube.out +++ b/contrib/cube/expected/cube.out @@ -258,46 +258,46 @@ SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube; SELECT ''::cube AS cube; ERROR: cube_in: can't parse an empty string SELECT 'ABC'::cube AS cube; -ERROR: parse error at or before position 1, character ('A', \101), input: 'ABC' +ERROR: syntax error at or before position 1, character ('A', \101), input: 'ABC' SELECT '()'::cube AS cube; -ERROR: parse error at or before position 2, character (')', \051), input: '()' +ERROR: syntax error at or before position 2, character (')', \051), input: '()' SELECT '[]'::cube AS cube; -ERROR: parse error at or before position 2, character (']', \135), input: '[]' +ERROR: syntax error at or before position 2, character (']', \135), input: '[]' SELECT '[()]'::cube AS cube; -ERROR: parse error at or before position 3, character (')', \051), input: '[()]' +ERROR: syntax error at or before position 3, character (')', \051), input: '[()]' SELECT '[(1)]'::cube AS cube; -ERROR: parse error at or before position 5, character (']', \135), input: '[(1)]' +ERROR: syntax error at or before position 5, character (']', \135), input: '[(1)]' SELECT '[(1),]'::cube AS cube; -ERROR: parse error at or before position 6, character (']', \135), input: '[(1),]' +ERROR: syntax error at or before position 6, character (']', \135), input: '[(1),]' SELECT '[(1),2]'::cube AS cube; -ERROR: parse error at or before position 7, character (']', \135), input: '[(1),2]' +ERROR: syntax error at or before position 7, character (']', \135), input: '[(1),2]' SELECT '[(1),(2),(3)]'::cube AS cube; -ERROR: parse error at or before position 9, character (',', \054), input: '[(1),(2),(3)]' +ERROR: syntax error at or before position 9, character (',', \054), input: '[(1),(2),(3)]' SELECT '1,'::cube AS cube; -ERROR: parse error at or before position 2, character (',', \054), input: '1,' +ERROR: syntax error at or before position 2, character (',', \054), input: '1,' SELECT '1,2,'::cube AS cube; -ERROR: parse error at or before position 4, character (',', \054), input: '1,2,' +ERROR: syntax error at or before position 4, character (',', \054), input: '1,2,' SELECT '1,,2'::cube AS cube; -ERROR: parse error at or before position 3, character (',', \054), input: '1,,2' +ERROR: syntax error at or before position 3, character (',', \054), input: '1,,2' SELECT '(1,)'::cube AS cube; -ERROR: parse error at or before position 4, character (')', \051), input: '(1,)' +ERROR: syntax error at or before position 4, character (')', \051), input: '(1,)' SELECT '(1,2,)'::cube AS cube; -ERROR: parse error at or before position 6, character (')', \051), input: '(1,2,)' +ERROR: syntax error at or before position 6, character (')', \051), input: '(1,2,)' SELECT '(1,,2)'::cube AS cube; -ERROR: parse error at or before position 4, character (',', \054), input: '(1,,2)' +ERROR: syntax error at or before position 4, character (',', \054), input: '(1,,2)' -- invalid input: semantic errors and trailing garbage SELECT '[(1),(2)],'::cube AS cube; -- 0 @@ -339,6 +339,60 @@ ERROR: (7) bad cube representation; garbage at or before char 4, ('end of input SELECT '1..2'::cube AS cube; -- 7 ERROR: (7) bad cube representation; garbage at or before char 4, ('end of input', \000) +-- +-- Testing building cubes from float8 values +-- +SELECT cube(0::float8); + cube +------ + (0) +(1 row) + +SELECT cube(1::float8); + cube +------ + (1) +(1 row) + +SELECT cube(1,2); + cube +--------- + (1),(2) +(1 row) + +SELECT cube(cube(1,2),3); + cube +--------------- + (1, 3),(2, 3) +(1 row) + +SELECT cube(cube(1,2),3,4); + cube +--------------- + (1, 3),(2, 4) +(1 row) + +SELECT cube(cube(cube(1,2),3,4),5); + cube +--------------------- + (1, 3, 5),(2, 4, 5) +(1 row) + +SELECT cube(cube(cube(1,2),3,4),5,6); + cube +--------------------- + (1, 3, 5),(2, 4, 6) +(1 row) + +-- +-- Test that the text -> cube cast was installed. +-- +SELECT '(0)'::text::cube; + cube +------ + (0) +(1 row) + -- -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in. -- diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql index a0712c5557..d386a5a2f3 100644 --- a/contrib/cube/sql/cube.sql +++ b/contrib/cube/sql/cube.sql @@ -92,6 +92,24 @@ SELECT '1 e7'::cube AS cube; -- 6 SELECT '1,2a'::cube AS cube; -- 7 SELECT '1..2'::cube AS cube; -- 7 +-- +-- Testing building cubes from float8 values +-- + +SELECT cube(0::float8); +SELECT cube(1::float8); +SELECT cube(1,2); +SELECT cube(cube(1,2),3); +SELECT cube(cube(1,2),3,4); +SELECT cube(cube(cube(1,2),3,4),5); +SELECT cube(cube(cube(1,2),3,4),5,6); + +-- +-- Test that the text -> cube cast was installed. +-- + +SELECT '(0)'::text::cube; + -- -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in. --