@ -272,9 +272,9 @@ 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 void array_to_datum_internal ( AV * av , ArrayBuildState * astate ,
static void array_to_datum_internal ( AV * av , ArrayBuildState * * astatep ,
int * ndims , int * dims , int cur_depth ,
Oid arraytypid , Oid elemtypid , int32 typmod ,
Oid elemtypid , int32 typmod ,
FmgrInfo * finfo , Oid typioparam ) ;
static Datum plperl_hash_to_datum ( SV * src , TupleDesc td ) ;
@ -1160,11 +1160,16 @@ get_perl_array_ref(SV *sv)
/*
* helper function for plperl_array_to_datum , recurses for multi - D arrays
*
* The ArrayBuildState is created only when we first find a scalar element ;
* if we didn ' t do it like that , we ' d need some other convention for knowing
* whether we ' d already found any scalars ( and thus the number of dimensions
* is frozen ) .
*/
static void
array_to_datum_internal ( AV * av , ArrayBuildState * astate ,
array_to_datum_internal ( AV * av , ArrayBuildState * * astatep ,
int * ndims , int * dims , int cur_depth ,
Oid arraytypid , Oid elemtypid , int32 typmod ,
Oid elemtypid , int32 typmod ,
FmgrInfo * finfo , Oid typioparam )
{
dTHX ;
@ -1184,28 +1189,34 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
{
AV * nav = ( AV * ) SvRV ( sav ) ;
/* dimensionality checks */
/* set size when at first element in this level, else compare */
if ( i = = 0 & & * ndims = = cur_depth )
{
/* array after some scalars at same level? */
if ( * astatep ! = NULL )
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " multidimensional arrays must have array expressions with matching dimensions " ) ) ) ;
/* too many dimensions? */
if ( cur_depth + 1 > MAXDIM )
ereport ( ERROR ,
( errcode ( ERRCODE_PROGRAM_LIMIT_EXCEEDED ) ,
errmsg ( " number of array dimensions (%d) exceeds the maximum allowed (%d) " ,
cur_depth + 1 , MAXDIM ) ) ) ;
/* set size when at first element in this level, else compare */
if ( i = = 0 & & * ndims = = cur_depth )
{
/* OK, add a dimension */
dims [ * ndims ] = av_len ( nav ) + 1 ;
( * ndims ) + + ;
}
else if ( av_len ( nav ) + 1 ! = dims [ cur_depth ] )
else if ( cur_depth > = * ndims | |
av_len ( nav ) + 1 ! = dims [ cur_depth ] )
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " multidimensional arrays must have array expressions with matching dimensions " ) ) ) ;
/* recurse to fetch elements of this sub-array */
array_to_datum_internal ( nav , astate ,
array_to_datum_internal ( nav , astatep ,
ndims , dims , cur_depth + 1 ,
arraytypid , elemtypid , typmod ,
elemtypid , typmod ,
finfo , typioparam ) ;
}
else
@ -1227,7 +1238,13 @@ array_to_datum_internal(AV *av, ArrayBuildState *astate,
typioparam ,
& isnull ) ;
( void ) accumArrayResult ( astate , dat , isnull ,
/* Create ArrayBuildState if we didn't already */
if ( * astatep = = NULL )
* astatep = initArrayResult ( elemtypid ,
CurrentMemoryContext , true ) ;
/* ... and save the element value in it */
( void ) accumArrayResult ( * astatep , dat , isnull ,
elemtypid , CurrentMemoryContext ) ;
}
}
@ -1240,7 +1257,8 @@ static Datum
plperl_array_to_datum ( SV * src , Oid typid , int32 typmod )
{
dTHX ;
ArrayBuildState * astate ;
AV * nav = ( AV * ) SvRV ( src ) ;
ArrayBuildState * astate = NULL ;
Oid elemtypid ;
FmgrInfo finfo ;
Oid typioparam ;
@ -1256,21 +1274,19 @@ 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 , true ) ;
_sv_to_datum_finfo ( elemtypid , & finfo , & typioparam ) ;
memset ( dims , 0 , sizeof ( dims ) ) ;
dims [ 0 ] = av_len ( ( AV * ) S vRV ( src ) ) + 1 ;
dims [ 0 ] = av_len ( na v) + 1 ;
array_to_datum_internal ( ( AV * ) SvRV ( src ) , astate ,
array_to_datum_internal ( nav , & astate ,
& ndims , dims , 1 ,
typid , elemtypid , typmod ,
elemtypid , typmod ,
& finfo , typioparam ) ;
/* ensure we get zero-D array for no inputs, as per PG convention */
if ( dims [ 0 ] < = 0 )
ndims = 0 ;
if ( astate = = NULL )
return PointerGetDatum ( construct_empty_array ( elemtypid ) ) ;
for ( i = 0 ; i < ndims ; i + + )
lbs [ i ] = 1 ;