aboutsummaryrefslogtreecommitdiff
path: root/src/include/utils/array.h
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-11-25 12:21:22 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2014-11-25 12:21:28 -0500
commitbac27394a1c69c20ec904729c593e59485c75c69 (patch)
tree7bdf15b078bfcef745a5bb2c7c479d6f8bd45f15 /src/include/utils/array.h
parent25976710dfd8611d3fc79c0c1e20179ff7a940ec (diff)
downloadpostgresql-bac27394a1c69c20ec904729c593e59485c75c69.tar.gz
postgresql-bac27394a1c69c20ec904729c593e59485c75c69.zip
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/utils/array.h')
-rw-r--r--src/include/utils/array.h55
1 files changed, 55 insertions, 0 deletions
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