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/pl/plperl/plperl.c | |
parent | 25976710dfd8611d3fc79c0c1e20179ff7a940ec (diff) | |
download | postgresql-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/pl/plperl/plperl.c')
-rw-r--r-- | src/pl/plperl/plperl.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 1d025d46533..56295715a18 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -268,7 +268,7 @@ static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod, bool *isnull); static void _sv_to_datum_finfo(Oid typid, FmgrInfo *finfo, Oid *typioparam); static Datum plperl_array_to_datum(SV *src, Oid typid, int32 typmod); -static ArrayBuildState *array_to_datum_internal(AV *av, ArrayBuildState *astate, +static void array_to_datum_internal(AV *av, ArrayBuildState *astate, int *ndims, int *dims, int cur_depth, Oid arraytypid, Oid elemtypid, int32 typmod, FmgrInfo *finfo, Oid typioparam); @@ -1127,7 +1127,7 @@ get_perl_array_ref(SV *sv) /* * helper function for plperl_array_to_datum, recurses for multi-D arrays */ -static ArrayBuildState * +static void array_to_datum_internal(AV *av, ArrayBuildState *astate, int *ndims, int *dims, int cur_depth, Oid arraytypid, Oid elemtypid, int32 typmod, @@ -1168,10 +1168,10 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate, errmsg("multidimensional arrays must have array expressions with matching dimensions"))); /* recurse to fetch elements of this sub-array */ - astate = array_to_datum_internal(nav, astate, - ndims, dims, cur_depth + 1, - arraytypid, elemtypid, typmod, - finfo, typioparam); + array_to_datum_internal(nav, astate, + ndims, dims, cur_depth + 1, + arraytypid, elemtypid, typmod, + finfo, typioparam); } else { @@ -1192,12 +1192,10 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate, typioparam, &isnull); - astate = accumArrayResult(astate, dat, isnull, - elemtypid, CurrentMemoryContext); + (void) accumArrayResult(astate, dat, isnull, + elemtypid, CurrentMemoryContext); } } - - return astate; } /* @@ -1222,18 +1220,21 @@ plperl_array_to_datum(SV *src, Oid typid, int32 typmod) errmsg("cannot convert Perl array to non-array type %s", format_type_be(typid)))); + astate = initArrayResult(elemtypid, CurrentMemoryContext); + _sv_to_datum_finfo(elemtypid, &finfo, &typioparam); memset(dims, 0, sizeof(dims)); dims[0] = av_len((AV *) SvRV(src)) + 1; - astate = array_to_datum_internal((AV *) SvRV(src), NULL, - &ndims, dims, 1, - typid, elemtypid, typmod, - &finfo, typioparam); + array_to_datum_internal((AV *) SvRV(src), astate, + &ndims, dims, 1, + typid, elemtypid, typmod, + &finfo, typioparam); - if (!astate) - return PointerGetDatum(construct_empty_array(elemtypid)); + /* ensure we get zero-D array for no inputs, as per PG convention */ + if (dims[0] <= 0) + ndims = 0; for (i = 0; i < ndims; i++) lbs[i] = 1; |