diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2014-11-25 12:21:22 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2014-11-25 12:21:28 -0500 |
commit | bac27394a1c69c20ec904729c593e59485c75c69 (patch) | |
tree | 7bdf15b078bfcef745a5bb2c7c479d6f8bd45f15 /src/include | |
parent | 25976710dfd8611d3fc79c0c1e20179ff7a940ec (diff) |
Support arrays as input to array_agg() and ARRAY(SELECT ...).
These cases formerly failed with errors about "could not find array type
for data type". Now they yield arrays of the same element type and one
higher dimension.
The implementation involves creating functions with API similar to the
existing accumArrayResult() family. I (tgl) also extended the base family
by adding an initArrayResult() function, which allows callers to avoid
special-casing the zero-inputs case if they just want an empty array as
result. (Not all do, so the previous calling convention remains valid.)
This allowed simplifying some existing code in xml.c and plperl.c.
Ali Akbar, reviewed by Pavel Stehule, significantly modified by me
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_aggregate.h | 1 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 18 | ||||
-rw-r--r-- | src/include/utils/array.h | 55 | ||||
-rw-r--r-- | src/include/utils/lsyscache.h | 1 |
5 files changed, 70 insertions, 7 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index bdaf4176f6a..b670902b7d2 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201411111 +#define CATALOG_VERSION_NO 201411251 #endif diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 3ba9e5e1b26..32793537616 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -275,6 +275,7 @@ DATA(insert ( 2901 n 0 xmlconcat2 - - - - f f 0 142 0 0 0 _null_ /* array */ DATA(insert ( 2335 n 0 array_agg_transfn array_agg_finalfn - - - t f 0 2281 0 0 0 _null_ _null_ )); +DATA(insert ( 4053 n 0 array_agg_array_transfn array_agg_array_finalfn - - - t f 0 2281 0 0 0 _null_ _null_ )); /* text */ DATA(insert ( 3538 n 0 string_agg_transfn string_agg_finalfn - - - f f 0 2281 0 0 0 _null_ _null_ )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 5d4e889af45..56399ac5565 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -565,11 +565,11 @@ DESCR("btree(internal)"); DATA(insert OID = 2785 ( btoptions PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 17 "1009 16" _null_ _null_ _null_ _null_ btoptions _null_ _null_ _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 3789 ( bringetbitmap PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_ bringetbitmap _null_ _null_ _null_ )); +DATA(insert OID = 3789 ( bringetbitmap PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_ bringetbitmap _null_ _null_ _null_ )); DESCR("brin(internal)"); DATA(insert OID = 3790 ( brininsert PGNSP PGUID 12 1 0 0 0 f f f f t f v 6 0 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ brininsert _null_ _null_ _null_ )); DESCR("brin(internal)"); -DATA(insert OID = 3791 ( brinbeginscan PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ brinbeginscan _null_ _null_ _null_ )); +DATA(insert OID = 3791 ( brinbeginscan PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ brinbeginscan _null_ _null_ _null_ )); DESCR("brin(internal)"); DATA(insert OID = 3792 ( brinrescan PGNSP PGUID 12 1 0 0 0 f f f f t f v 5 0 2278 "2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ brinrescan _null_ _null_ _null_ )); DESCR("brin(internal)"); @@ -587,7 +587,7 @@ DATA(insert OID = 3798 ( brinbulkdelete PGNSP PGUID 12 1 0 0 0 f f f f t f v DESCR("brin(internal)"); DATA(insert OID = 3799 ( brinvacuumcleanup PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ brinvacuumcleanup _null_ _null_ _null_ )); DESCR("brin(internal)"); -DATA(insert OID = 3800 ( brincostestimate PGNSP PGUID 12 1 0 0 0 f f f f t f v 7 0 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ brincostestimate _null_ _null_ _null_ )); +DATA(insert OID = 3800 ( brincostestimate PGNSP PGUID 12 1 0 0 0 f f f f t f v 7 0 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ brincostestimate _null_ _null_ _null_ )); DESCR("brin(internal)"); DATA(insert OID = 3801 ( brinoptions PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 17 "1009 16" _null_ _null_ _null_ _null_ brinoptions _null_ _null_ _null_ )); DESCR("brin(internal)"); @@ -908,11 +908,17 @@ DATA(insert OID = 3167 ( array_remove PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 DESCR("remove any occurrences of an element from an array"); DATA(insert OID = 3168 ( array_replace PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 2277 "2277 2283 2283" _null_ _null_ _null_ _null_ array_replace _null_ _null_ _null_ )); DESCR("replace any occurrences of an element in an array"); -DATA(insert OID = 2333 ( array_agg_transfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 2283" _null_ _null_ _null_ _null_ array_agg_transfn _null_ _null_ _null_ )); +DATA(insert OID = 2333 ( array_agg_transfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 2776" _null_ _null_ _null_ _null_ array_agg_transfn _null_ _null_ _null_ )); DESCR("aggregate transition function"); -DATA(insert OID = 2334 ( array_agg_finalfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2277 "2281 2283" _null_ _null_ _null_ _null_ array_agg_finalfn _null_ _null_ _null_ )); +DATA(insert OID = 2334 ( array_agg_finalfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2277 "2281 2776" _null_ _null_ _null_ _null_ array_agg_finalfn _null_ _null_ _null_ )); DESCR("aggregate final function"); -DATA(insert OID = 2335 ( array_agg PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 2277 "2283" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); +DATA(insert OID = 2335 ( array_agg PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 2277 "2776" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); +DESCR("concatenate aggregate input into an array"); +DATA(insert OID = 4051 ( array_agg_array_transfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 2277" _null_ _null_ _null_ _null_ array_agg_array_transfn _null_ _null_ _null_ )); +DESCR("aggregate transition function"); +DATA(insert OID = 4052 ( array_agg_array_finalfn PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2277 "2281 2277" _null_ _null_ _null_ _null_ array_agg_array_finalfn _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 4053 ( array_agg PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 2277 "2277" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )); DESCR("concatenate aggregate input into an array"); DATA(insert OID = 3218 ( width_bucket PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "2283 2277" _null_ _null_ _null_ _null_ width_bucket_array _null_ _null_ _null_ )); DESCR("bucket number of operand given a sorted array of bucket lower bounds"); diff --git a/src/include/utils/array.h b/src/include/utils/array.h index e744314c51b..e1d57490168 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -76,6 +76,7 @@ typedef struct /* * working state for accumArrayResult() and friends + * note that the input must be scalars (legal array elements) */ typedef struct ArrayBuildState { @@ -91,6 +92,37 @@ typedef struct ArrayBuildState } ArrayBuildState; /* + * working state for accumArrayResultArr() and friends + * note that the input must be arrays, and the same array type is returned + */ +typedef struct ArrayBuildStateArr +{ + MemoryContext mcontext; /* where all the temp stuff is kept */ + char *data; /* accumulated data */ + bits8 *nullbitmap; /* bitmap of is-null flags, or NULL if none */ + int abytes; /* allocated length of "data" */ + int nbytes; /* number of bytes used so far */ + int aitems; /* allocated length of bitmap (in elements) */ + int nitems; /* total number of elements in result */ + int ndims; /* current dimensions of result */ + int dims[MAXDIM]; + int lbs[MAXDIM]; + Oid array_type; /* data type of the arrays */ + Oid element_type; /* data type of the array elements */ +} ArrayBuildStateArr; + +/* + * working state for accumArrayResultAny() and friends + * these functions handle both cases + */ +typedef struct ArrayBuildStateAny +{ + /* Exactly one of these is not NULL: */ + ArrayBuildState *scalarstate; + ArrayBuildStateArr *arraystate; +} ArrayBuildStateAny; + +/* * structure to cache type metadata needed for array manipulation */ typedef struct ArrayMetaState @@ -252,6 +284,9 @@ extern void deconstruct_array(ArrayType *array, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp); extern bool array_contains_nulls(ArrayType *array); + +extern ArrayBuildState *initArrayResult(Oid element_type, + MemoryContext rcontext); extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, @@ -261,6 +296,24 @@ extern Datum makeArrayResult(ArrayBuildState *astate, extern Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release); +extern ArrayBuildStateArr *initArrayResultArr(Oid array_type, Oid element_type, + MemoryContext rcontext); +extern ArrayBuildStateArr *accumArrayResultArr(ArrayBuildStateArr *astate, + Datum dvalue, bool disnull, + Oid array_type, + MemoryContext rcontext); +extern Datum makeArrayResultArr(ArrayBuildStateArr *astate, + MemoryContext rcontext, bool release); + +extern ArrayBuildStateAny *initArrayResultAny(Oid input_type, + MemoryContext rcontext); +extern ArrayBuildStateAny *accumArrayResultAny(ArrayBuildStateAny *astate, + Datum dvalue, bool disnull, + Oid input_type, + MemoryContext rcontext); +extern Datum makeArrayResultAny(ArrayBuildStateAny *astate, + MemoryContext rcontext, bool release); + extern ArrayIterator array_create_iterator(ArrayType *arr, int slice_ndim); extern bool array_iterate(ArrayIterator iterator, Datum *value, bool *isnull); extern void array_free_iterator(ArrayIterator iterator); @@ -292,6 +345,8 @@ extern ArrayType *create_singleton_array(FunctionCallInfo fcinfo, extern Datum array_agg_transfn(PG_FUNCTION_ARGS); extern Datum array_agg_finalfn(PG_FUNCTION_ARGS); +extern Datum array_agg_array_transfn(PG_FUNCTION_ARGS); +extern Datum array_agg_array_finalfn(PG_FUNCTION_ARGS); /* * prototypes for functions defined in array_typanalyze.c diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 07d24d4cb8a..1a556f8ae29 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -128,6 +128,7 @@ extern void get_type_category_preferred(Oid typid, extern Oid get_typ_typrelid(Oid typid); extern Oid get_element_type(Oid typid); extern Oid get_array_type(Oid typid); +extern Oid get_promoted_array_type(Oid typid); extern Oid get_base_element_type(Oid typid); extern void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam); extern void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena); |