Thread: Proposed patch for contrib/cube
Hi, I use the cube datatype a fair bit, and one thing I have always wanted is the ability to do this: pg=# select cube_from_arrays('{1,2,3}'::float[], '{3,5,6}'::float[]); cube_from_arrays --------------------- (1, 2, 3),(3, 5, 6) (1 row) That is - build a cube by specifying 2 arrays, one for the UR coordinate, one for LL. I hope people find this useful, and if so, we can add it to contrib/cube. Source is attached. Thanks, Joshua Reich (jdigittl on #postgresql) #include "postgres.h" #include "utils/array.h" #include "cubedata.h" /* contrib/cube */ /* ** CREATE OR REPLACE FUNCTION cube_from_arrays(float[], float[]) RETURNS cube ** AS 'ordermatch' ** LANGUAGE C; */ NDBOX *cube_from_arrays (ArrayType *ur, ArrayType *ll); /* ** Taken from the intarray contrib header */ #define ARRPTR(x) ( (double *) ARR_DATA_PTR(x) ) #define ARRNELEMS(x) ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x)) /* ** Allows the construction of a cube from 2 float[]'s */ NDBOX *cube_from_arrays (ArrayType *ur, ArrayType *ll) { int i; int dim; int size; NDBOX *result; double *dur, *dll; dim = ARRNELEMS(ur); if (ARRNELEMS(ll) < dim) { /* ** If the array's are not of equal length, use the length ** of the shorter array. */ dim = ARRNELEMS(ll); } dur = ARRPTR(ur); dll = ARRPTR(ll); size = offsetof(NDBOX, x[0]) + sizeof(double) * 2 * dim; result = (NDBOX *) palloc (size); memset (result, 0, size); result->size = size; result->dim = dim; for (i=0; i<dim; i++) { result->x[i] = dur[i]; result->x[i+dim] = dll[i]; } return result; }
Joshua Reich <josh@root.net> writes: > ... build a cube by specifying 2 arrays, one for the UR > coordinate, one for LL. > I hope people find this useful, and if so, we can add it to contrib/cube. Seems useful, but it needs work: it will fail on toasted arrays or arrays containing nulls. I'd suggest converting it to V1 call protocol too, as the V1 GETARG macros are the easiest answer to the toasting problem. Null array elements are a new issue in CVS HEAD, you'd need to test against HEAD for that. As a matter of style, would it be better to error out if the arrays are not the same length? regards, tom lane
Tom: Thanks for the out-of-band posting to the documentation. I think the new version (attached) addresses your issues. What is the general process for submitting patches? Is there a URL someone can point me towards to learn more? Thanks, Josh Reich Tom Lane wrote: > Joshua Reich <josh@root.net> writes: >> ... build a cube by specifying 2 arrays, one for the UR >> coordinate, one for LL. >> I hope people find this useful, and if so, we can add it to contrib/cube. > > Seems useful, but it needs work: it will fail on toasted arrays or > arrays containing nulls. I'd suggest converting it to V1 call protocol > too, as the V1 GETARG macros are the easiest answer to the toasting > problem. Null array elements are a new issue in CVS HEAD, you'd need > to test against HEAD for that. > > As a matter of style, would it be better to error out if the arrays > are not the same length? > > regards, tom lane > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Have you searched our list archives? > > http://archives.postgresql.org #include "postgres.h" #include "utils/array.h" #include "cubedata.h" /* contrib/cube */ #include "fmgr.h" /* ** CREATE OR REPLACE FUNCTION cube_from_arrays(float[], float[]) RETURNS cube ** AS 'cube_from_arrays' ** LANGUAGE C; */ /* ** Taken from the intarray contrib header */ #define ARRPTR(x) ( (double *) ARR_DATA_PTR(x) ) #define ARRNELEMS(x) ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x)) /* ** Allows the construction of a cube from 2 float[]'s */ PG_FUNCTION_INFO_V1(cube_from_arrays); NDBOX * cube_from_arrays (PG_FUNCTION_ARGS) { int i; int dim; int size; NDBOX *result; ArrayType *ur, *ll; double *dur, *dll; if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("Cannot work with NULL arrays"))); } ur = (ArrayType *) PG_GETARG_VARLENA_P(0); ll = (ArrayType *) PG_GETARG_VARLENA_P(1); dim = ARRNELEMS(ur); if (ARRNELEMS(ll) != dim) { ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("UR and LL arrays must be of same length"))); PG_RETURN_NULL(); } dur = ARRPTR(ur); dll = ARRPTR(ll); size = offsetof(NDBOX, x[0]) + sizeof(double) * 2 * dim; result = (NDBOX *) palloc (size); memset (result, 0, size); result->size = size; result->dim = dim; for (i=0; i<dim; i++) { result->x[i] = dur[i]; result->x[i+dim] = dll[i]; } PG_RETURN_DATUM(result); }
Josh, > What is the general process for submitting patches? Is there a URL > someone can point me towards to learn more? Send them in an e-mail to pgsql-patches. -- --Josh Josh Berkus PostgreSQL @ Sun San Francisco