@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / backend / utils / adt / arrayfuncs . c , v 1.60 2000 / 07 / 03 23 : 09 : 50 wieck Exp $
* $ Header : / cvsroot / pgsql / src / backend / utils / adt / arrayfuncs . c , v 1.61 2000 / 07 / 17 03 : 05 : 17 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -19,7 +19,6 @@
# include "catalog/catalog.h"
# include "catalog/catalog.h"
# include "catalog/pg_type.h"
# include "catalog/pg_type.h"
# include "fmgr.h"
# include "libpq/be-fsstubs.h"
# include "libpq/be-fsstubs.h"
# include "libpq/libpq-fs.h"
# include "libpq/libpq-fs.h"
# include "storage/fd.h"
# include "storage/fd.h"
@ -29,7 +28,8 @@
# define ASSGN "="
# define ASSGN "="
/* An array has the following internal structure:
/*
* An array has the following internal structure :
* < nbytes > - total number of bytes
* < nbytes > - total number of bytes
* < ndim > - number of dimensions of the array
* < ndim > - number of dimensions of the array
* < flags > - bit mask of flags
* < flags > - bit mask of flags
@ -38,20 +38,18 @@
* < actual data > - whatever is the stored data
* < actual data > - whatever is the stored data
*/
*/
/*-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-*/
static int _ArrayCount ( char * str , int * dim , int typdelim ) ;
static int _ArrayCount ( char * str , int * dim , int typdelim ) ;
static char * _ ReadArrayStr( char * arrayStr , int nitems , int ndim , int * dim ,
static Datum * ReadArrayStr ( char * arrayStr , int nitems , int ndim , int * dim ,
FmgrInfo * inputproc , Oid typelem , int32 typmod ,
FmgrInfo * inputproc , Oid typelem , int32 typmod ,
char typdelim , int typlen , bool typbyval ,
char typdelim , int typlen , bool typbyval ,
char typalign , int * nbytes ) ;
char typalign , int * nbytes ) ;
# ifdef LOARRAY
# ifdef LOARRAY
static char * _ReadLOArray ( char * str , int * nbytes , int * fd , bool * chunkFlag ,
static char * _ReadLOArray ( char * str , int * nbytes , int * fd , bool * chunkFlag ,
int ndim , int * dim , int baseSize ) ;
int ndim , int * dim , int baseSize ) ;
# endif
# endif
static void _CopyArrayEls ( char * * values , char * p , int nitems , int typlen ,
static void CopyArrayEls ( char * p , Datum * values , int nitems ,
char typalign , bool typbyval ) ;
bool typbyval , int typlen , char typalign ,
bool freedata ) ;
static void system_cache_lookup ( Oid element_type , bool input , int * typlen ,
static void system_cache_lookup ( Oid element_type , bool input , int * typlen ,
bool * typbyval , char * typdelim , Oid * typelem , Oid * proc ,
bool * typbyval , char * typdelim , Oid * typelem , Oid * proc ,
char * typalign ) ;
char * typalign ) ;
@ -101,7 +99,7 @@ array_in(PG_FUNCTION_ARGS)
int i ,
int i ,
nitems ;
nitems ;
int32 nbytes ;
int32 nbytes ;
char * dataPtr ;
Datum * dataPtr ;
ArrayType * retval ;
ArrayType * retval ;
int ndim ,
int ndim ,
dim [ MAXDIM ] ,
dim [ MAXDIM ] ,
@ -187,32 +185,29 @@ array_in(PG_FUNCTION_ARGS)
retval = ( ArrayType * ) palloc ( sizeof ( ArrayType ) ) ;
retval = ( ArrayType * ) palloc ( sizeof ( ArrayType ) ) ;
MemSet ( retval , 0 , sizeof ( ArrayType ) ) ;
MemSet ( retval , 0 , sizeof ( ArrayType ) ) ;
* ( int32 * ) retval = sizeof ( ArrayType ) ;
* ( int32 * ) retval = sizeof ( ArrayType ) ;
PG_RETURN_POINTER ( retval ) ;
PG_RETURN_ARRAYTYPE_P ( retval ) ;
}
}
if ( * p = = ' { ' )
if ( * p = = ' { ' )
{
{
/* array not a large object */
/* array not a large object */
dataPtr = ( char * ) _ ReadArrayStr( p , nitems , ndim , dim , & inputproc , typelem ,
dataPtr = ReadArrayStr ( p , nitems , ndim , dim , & inputproc , typelem ,
typmod , typdelim , typlen , typbyval , typalign ,
typmod , typdelim , typlen , typbyval , typalign ,
& nbytes ) ;
& nbytes ) ;
nbytes + = ARR_OVERHEAD ( ndim ) ;
nbytes + = ARR_OVERHEAD ( ndim ) ;
retval = ( ArrayType * ) palloc ( nbytes ) ;
retval = ( ArrayType * ) palloc ( nbytes ) ;
MemSet ( retval , 0 , nbytes ) ;
MemSet ( retval , 0 , nbytes ) ;
memmove ( retval , ( char * ) & nbytes , sizeof ( int ) ) ;
retval - > size = nbytes ;
memmove ( ( char * ) ARR_NDIM_PTR ( retval ) , ( char * ) & ndim , sizeof ( int ) ) ;
retval - > ndim = ndim ;
SET_LO_FLAG ( false , retval ) ;
SET_LO_FLAG ( false , retval ) ;
memmove ( ( char * ) ARR_DIMS ( retval ) , ( char * ) dim , ndim * sizeof ( int ) ) ;
memcpy ( ( char * ) ARR_DIMS ( retval ) , ( char * ) dim ,
memmove ( ( char * ) ARR_LBOUND ( retval ) , ( char * ) lBound ,
ndim * sizeof ( int ) ) ;
ndim * sizeof ( int ) ) ;
memcpy ( ( char * ) ARR_LBOUND ( retval ) , ( char * ) lBound ,
ndim * sizeof ( int ) ) ;
/*
* dataPtr is an array of arbitraystuff even though its type is
CopyArrayEls ( ARR_DATA_PTR ( retval ) , dataPtr , nitems ,
* char * cast to char * * to pass to _CopyArrayEls for now - jolly
typbyval , typlen , typalign , true ) ;
*/
pfree ( dataPtr ) ;
_CopyArrayEls ( ( char * * ) dataPtr ,
ARR_DATA_PTR ( retval ) , nitems ,
typlen , typalign , typbyval ) ;
}
}
else
else
{
{
@ -226,8 +221,8 @@ array_in(PG_FUNCTION_ARGS)
nbytes = bytes + ARR_OVERHEAD ( ndim ) ;
nbytes = bytes + ARR_OVERHEAD ( ndim ) ;
retval = ( ArrayType * ) palloc ( nbytes ) ;
retval = ( ArrayType * ) palloc ( nbytes ) ;
MemSet ( retval , 0 , nbytes ) ;
MemSet ( retval , 0 , nbytes ) ;
memmove ( retval , ( char * ) & nbytes , sizeof ( int ) ) ;
retval - > size = nbytes ;
memmove ( ( char * ) ARR_NDIM_PTR ( retval ) , ( char * ) & ndim , sizeof ( int ) ) ;
retval - > ndim = ndim ;
SET_LO_FLAG ( true , retval ) ;
SET_LO_FLAG ( true , retval ) ;
SET_CHUNK_FLAG ( chunked , retval ) ;
SET_CHUNK_FLAG ( chunked , retval ) ;
memmove ( ( char * ) ARR_DIMS ( retval ) , ( char * ) dim , ndim * sizeof ( int ) ) ;
memmove ( ( char * ) ARR_DIMS ( retval ) , ( char * ) dim , ndim * sizeof ( int ) ) ;
@ -238,7 +233,7 @@ array_in(PG_FUNCTION_ARGS)
PG_RETURN_NULL ( ) ;
PG_RETURN_NULL ( ) ;
}
}
pfree ( string_save ) ;
pfree ( string_save ) ;
PG_RETURN_POINTER ( retval ) ;
PG_RETURN_ARRAYTYPE_P ( retval ) ;
}
}
/*-----------------------------------------------------------------------------
/*-----------------------------------------------------------------------------
@ -331,50 +326,51 @@ _ArrayCount(char *str, int *dim, int typdelim)
}
}
/*---------------------------------------------------------------------------
/*---------------------------------------------------------------------------
* _ ReadArrayStr :
* ReadArrayStr :
* parses the array string pointed by " arrayStr " and converts it in the
* parses the array string pointed by " arrayStr " and converts it to
* internal format . The external format expected is like C array
* internal format . The external format expected is like C array
* declaration . Unspecified elements are initialized to zero for fixed length
* declaration . Unspecified elements are initialized to zero for fixed length
* base types and to empty varlena structures for variable length base
* base types and to empty varlena structures for variable length base
* types .
* types .
* result :
* result :
* returns the internal representation of the array elements
* returns a palloc ' d array of Datum representations of the array elements .
* nbytes is set to the size of the array in its internal representation .
* If element type is pass - by - ref , the Datums point to palloc ' d values .
* * nbytes is set to the amount of data space needed for the array ,
* including alignment padding but not including array header overhead .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
static char *
static Datum *
_ReadArrayStr ( char * arrayStr ,
ReadArrayStr ( char * arrayStr ,
int nitems ,
int nitems ,
int ndim ,
int ndim ,
int * dim ,
int * dim ,
FmgrInfo * inputproc , /* function used for the
FmgrInfo * inputproc ,
* conversion */
Oid typelem ,
Oid typelem ,
int32 typmod ,
int32 typmod ,
char typdelim ,
char typdelim ,
int typlen ,
int typlen ,
bool typbyval ,
bool typbyval ,
char typalign ,
char typalign ,
int * nbytes )
int * nbytes )
{
{
int i ,
int i ,
nest_level = 0 ;
nest_level = 0 ;
Datum * values ;
char * p ,
char * p ,
* q ,
* q ,
* r ,
* r ;
* * values ;
bool scanning_string = false ;
bool scanning_string = false ;
int indx [ MAXDIM ] ,
int indx [ MAXDIM ] ,
prod [ MAXDIM ] ;
prod [ MAXDIM ] ;
bool eoArray = false ;
bool eoArray = false ;
mda_get_prod ( ndim , dim , prod ) ;
mda_get_prod ( ndim , dim , prod ) ;
for ( i = 0 ; i < ndim ; indx [ i + + ] = 0 ) ;
values = ( Datum * ) palloc ( nitems * sizeof ( Datum ) ) ;
/* read array enclosed within {} */
MemSet ( values , 0 , nitems * sizeof ( Datum ) ) ;
values = ( char * * ) palloc ( nitems * sizeof ( char * ) ) ;
MemSet ( indx , 0 , sizeof ( indx ) ) ;
MemSet ( values , 0 , nitems * sizeof ( char * ) ) ;
q = p = arrayStr ;
q = p = arrayStr ;
/* read array enclosed within {} */
while ( ! eoArray )
while ( ! eoArray )
{
{
bool done = false ;
bool done = false ;
@ -442,53 +438,56 @@ _ReadArrayStr(char *arrayStr,
* q = ' \0 ' ;
* q = ' \0 ' ;
if ( i > = nitems )
if ( i > = nitems )
elog ( ERROR , " array_in: illformed array constant " ) ;
elog ( ERROR , " array_in: illformed array constant " ) ;
values [ i ] = ( char * ) FunctionCall3 ( inputproc ,
values [ i ] = FunctionCall3 ( inputproc ,
CStringGetDatum ( p ) ,
CStringGetDatum ( p ) ,
ObjectIdGetDatum ( typelem ) ,
ObjectIdGetDatum ( typelem ) ,
Int32GetDatum ( typmod ) ) ;
Int32GetDatum ( typmod ) ) ;
p = + + q ;
p = + + q ;
/*
* if not at the end of the array skip white space
*/
if ( ! eoArray )
if ( ! eoArray )
/*
* if not at the end of the array skip white space
*/
while ( isspace ( ( int ) * q ) )
while ( isspace ( ( int ) * q ) )
{
{
p + + ;
p + + ;
q + + ;
q + + ;
}
}
}
}
/*
* Initialize any unset items and compute total data space needed
*/
if ( typlen > 0 )
if ( typlen > 0 )
{
{
* nbytes = nitems * typlen ;
* nbytes = nitems * typlen ;
if ( ! typbyval )
if ( ! typbyval )
for ( i = 0 ; i < nitems ; i + + )
for ( i = 0 ; i < nitems ; i + + )
if ( ! values [ i ] )
if ( values [ i ] = = ( Datum ) 0 )
{
{
values [ i ] = palloc ( typlen ) ;
values [ i ] = PointerGetDatum ( palloc ( typlen ) ) ;
MemSet ( values [ i ] , 0 , typlen ) ;
MemSet ( DatumGetPointer ( values [ i ] ) , 0 , typlen ) ;
}
}
}
}
else
else
{
{
for ( i = 0 , * nbytes = 0 ; i < nitems ; i + + )
* nbytes = 0 ;
for ( i = 0 ; i < nitems ; i + + )
{
{
if ( values [ i ] )
if ( values [ i ] ! = ( Datum ) 0 )
{
{
if ( typalign = = ' d ' )
if ( typalign = = ' d ' )
* nbytes + = MAXALIGN ( * ( int32 * ) values [ i ] ) ;
* nbytes + = MAXALIGN ( VARSIZE ( DatumGetPointer ( values [ i ] ) ) ) ;
else
else
* nbytes + = INTALIGN ( * ( int32 * ) values [ i ] ) ;
* nbytes + = INTALIGN ( VARSIZE ( DatumGetPointer ( values [ i ] ) ) ) ;
}
}
else
else
{
{
* nbytes + = sizeof ( int32 ) ;
* nbytes + = sizeof ( int32 ) ;
values [ i ] = palloc ( sizeof ( int32 ) ) ;
values [ i ] = PointerGetDatum ( palloc ( sizeof ( int32 ) ) ) ;
* ( int32 * ) values [ i ] = sizeof ( int32 ) ;
VARATT_SIZEP ( DatumGetPointer ( values [ i ] ) ) = sizeof ( int32 ) ;
}
}
}
}
}
}
return ( char * ) values ;
return values ;
}
}
@ -565,26 +564,39 @@ _ReadLOArray(char *str,
# endif
# endif
/*----------
* Copy data into an array object from a temporary array of Datums .
*
* p : pointer to start of array data area
* values : array of Datums to be copied
* nitems : number of Datums to be copied
* typbyval , typlen , typalign : info about element datatype
* freedata : if TRUE and element type is pass - by - ref , pfree data values
* referenced by Datums after copying them .
* - - - - - - - - - -
*/
static void
static void
_CopyArrayEls ( char * * values ,
CopyArrayEls ( char * p ,
char * p ,
Datum * values ,
int nitems ,
int nitems ,
int typlen ,
bool typbyval ,
char typalign ,
int typlen ,
bool typbyval )
char typalign ,
bool freedata )
{
{
int i ;
int i ;
int inc ;
if ( typbyval )
freedata = false ;
for ( i = 0 ; i < nitems ; i + + )
for ( i = 0 ; i < nitems ; i + + )
{
{
int inc ;
inc = ArrayCastAndSet ( values [ i ] , typbyval , typlen , p ) ;
inc = ArrayCastAndSet ( ( Datum ) values [ i ] , typbyval , typlen , p ) ;
p + = inc ;
p + = inc ;
if ( ! typbyv al )
if ( freedata )
pfree ( values [ i ] ) ;
pfree ( DatumGetPointer ( values [ i ] ) ) ;
}
}
pfree ( values ) ;
}
}
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
@ -596,7 +608,7 @@ _CopyArrayEls(char **values,
Datum
Datum
array_out ( PG_FUNCTION_ARGS )
array_out ( PG_FUNCTION_ARGS )
{
{
ArrayType * v = ( ArrayType * ) PG_GETARG_VARLENA _P( 0 ) ;
ArrayType * v = PG_GETARG_ARRAYTYPE _P( 0 ) ;
Oid element_type = PG_GETARG_OID ( 1 ) ;
Oid element_type = PG_GETARG_OID ( 1 ) ;
int typlen ;
int typlen ;
bool typbyval ;
bool typbyval ;
@ -786,7 +798,7 @@ array_out(PG_FUNCTION_ARGS)
Datum
Datum
array_dims ( PG_FUNCTION_ARGS )
array_dims ( PG_FUNCTION_ARGS )
{
{
ArrayType * v = ( ArrayType * ) PG_GETARG_VARLENA _P( 0 ) ;
ArrayType * v = PG_GETARG_ARRAYTYPE _P( 0 ) ;
text * result ;
text * result ;
char * p ;
char * p ;
int nbytes ,
int nbytes ,
@ -821,8 +833,8 @@ array_dims(PG_FUNCTION_ARGS)
/*---------------------------------------------------------------------------
/*---------------------------------------------------------------------------
* array_ref :
* array_ref :
* This routine takes an array pointer and an index array and returns
* This routine takes an array pointer and an index array and returns
* a pointer to the referred element if element is passed by
* the referenced item as a Datum . Note that for a pass - by - reference
* reference otherwise returns the value of the referred elemen t.
* datatype , the returned Datum is a pointer into the array objec t.
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
Datum
Datum
@ -905,7 +917,7 @@ array_ref(ArrayType *array,
{ /* not by value */
{ /* not by value */
char * tempdata = palloc ( elmlen ) ;
char * tempdata = palloc ( elmlen ) ;
memmove ( tempdata , DatumGetPointer ( result ) , elmlen ) ;
memcpy ( tempdata , DatumGetPointer ( result ) , elmlen ) ;
result = PointerGetDatum ( tempdata ) ;
result = PointerGetDatum ( tempdata ) ;
}
}
pfree ( v ) ;
pfree ( v ) ;
@ -1003,14 +1015,15 @@ array_clip(ArrayType *array,
# endif
# endif
bytes = strlen ( newname ) + 1 + ARR_OVERHEAD ( nSubscripts ) ;
bytes = strlen ( newname ) + 1 + ARR_OVERHEAD ( nSubscripts ) ;
newArr = ( ArrayType * ) palloc ( bytes ) ;
newArr = ( ArrayType * ) palloc ( bytes ) ;
memmove ( newArr , array , sizeof ( ArrayType ) ) ;
newArr - > size = bytes ;
memmove ( newArr , & bytes , sizeof ( int ) ) ;
newArr - > ndim = array - > ndim ;
memmove ( ARR_DIMS ( newArr ) , span , nSubscripts * sizeof ( int ) ) ;
newArr - > flags = array - > flags ;
memmove ( ARR_LBOUND ( newArr ) , lowerIndx , nSubscripts * sizeof ( int ) ) ;
memcpy ( ARR_DIMS ( newArr ) , span , nSubscripts * sizeof ( int ) ) ;
memcpy ( ARR_LBOUND ( newArr ) , lowerIndx , nSubscripts * sizeof ( int ) ) ;
strcpy ( ARR_DATA_PTR ( newArr ) , newname ) ;
strcpy ( ARR_DATA_PTR ( newArr ) , newname ) ;
rsize = compute_size ( lowerIndx , upperIndx , nSubscripts , elmlen ) ;
rsize = compute_size ( lowerIndx , upperIndx , nSubscripts , elmlen ) ;
if ( rsize < MAX_BUFF_SIZE )
if ( rsize < BLCKSZ )
{
{
char * buff ;
char * buff ;
@ -1072,10 +1085,11 @@ array_clip(ArrayType *array,
bytes + = ARR_OVERHEAD ( nSubscripts ) ;
bytes + = ARR_OVERHEAD ( nSubscripts ) ;
}
}
newArr = ( ArrayType * ) palloc ( bytes ) ;
newArr = ( ArrayType * ) palloc ( bytes ) ;
memmove ( newArr , array , sizeof ( ArrayType ) ) ;
newArr - > size = bytes ;
memmove ( newArr , & bytes , sizeof ( int ) ) ;
newArr - > ndim = array - > ndim ;
memmove ( ARR_DIMS ( newArr ) , span , nSubscripts * sizeof ( int ) ) ;
newArr - > flags = array - > flags ;
memmove ( ARR_LBOUND ( newArr ) , lowerIndx , nSubscripts * sizeof ( int ) ) ;
memcpy ( ARR_DIMS ( newArr ) , span , nSubscripts * sizeof ( int ) ) ;
memcpy ( ARR_LBOUND ( newArr ) , lowerIndx , nSubscripts * sizeof ( int ) ) ;
_ArrayRange ( lowerIndx , upperIndx , elmlen , ARR_DATA_PTR ( newArr ) , array , 1 ) ;
_ArrayRange ( lowerIndx , upperIndx , elmlen , ARR_DATA_PTR ( newArr ) , array , 1 ) ;
return newArr ;
return newArr ;
}
}
@ -1322,7 +1336,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
{
{
ArrayType * v ;
ArrayType * v ;
ArrayType * result ;
ArrayType * result ;
char * * values ;
Datum * values ;
char * elt ;
char * elt ;
int * dim ;
int * dim ;
int ndim ;
int ndim ;
@ -1338,14 +1352,13 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
Oid proc ;
Oid proc ;
char typalign ;
char typalign ;
char * s ;
char * s ;
char * p ;
/* Get input array */
/* Get input array */
if ( fcinfo - > nargs < 1 )
if ( fcinfo - > nargs < 1 )
elog ( ERROR , " array_map: invalid nargs: %d " , fcinfo - > nargs ) ;
elog ( ERROR , " array_map: invalid nargs: %d " , fcinfo - > nargs ) ;
if ( PG_ARGISNULL ( 0 ) )
if ( PG_ARGISNULL ( 0 ) )
elog ( ERROR , " array_map: null input array " ) ;
elog ( ERROR , " array_map: null input array " ) ;
v = ( ArrayType * ) PG_GETARG_VARLENA _P( 0 ) ;
v = PG_GETARG_ARRAYTYPE _P( 0 ) ;
/* Large objects not yet supported */
/* Large objects not yet supported */
if ( ARR_IS_LO ( v ) = = true )
if ( ARR_IS_LO ( v ) = = true )
@ -1357,7 +1370,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
/* Check for empty array */
/* Check for empty array */
if ( nitems < = 0 )
if ( nitems < = 0 )
PG_RETURN_POINTER ( v ) ;
PG_RETURN_ARRAYTYPE_P ( v ) ;
/* Lookup source and result types. Unneeded variables are reused. */
/* Lookup source and result types. Unneeded variables are reused. */
system_cache_lookup ( inpType , false , & inp_typlen , & inp_typbyval ,
system_cache_lookup ( inpType , false , & inp_typlen , & inp_typbyval ,
@ -1366,8 +1379,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
& typdelim , & typelem , & proc , & typalign ) ;
& typdelim , & typelem , & proc , & typalign ) ;
/* Allocate temporary array for new values */
/* Allocate temporary array for new values */
values = ( char * * ) palloc ( nitems * sizeof ( char * ) ) ;
values = ( Datum * ) palloc ( nitems * sizeof ( Datum ) ) ;
MemSet ( values , 0 , nitems * sizeof ( char * ) ) ;
MemSet ( values , 0 , nitems * sizeof ( Datum ) ) ;
/* Loop over source data */
/* Loop over source data */
s = ( char * ) ARR_DATA_PTR ( v ) ;
s = ( char * ) ARR_DATA_PTR ( v ) ;
@ -1411,30 +1424,16 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
fcinfo - > arg [ 0 ] = ( Datum ) elt ;
fcinfo - > arg [ 0 ] = ( Datum ) elt ;
fcinfo - > argnull [ 0 ] = false ;
fcinfo - > argnull [ 0 ] = false ;
fcinfo - > isnull = false ;
fcinfo - > isnull = false ;
p = ( char * ) FunctionCallInvoke ( fcinfo ) ;
values [ i ] = FunctionCallInvoke ( fcinfo ) ;
if ( fcinfo - > isnull )
if ( fcinfo - > isnull )
elog ( ERROR , " array_map: cannot handle NULL in array " ) ;
elog ( ERROR , " array_map: cannot handle NULL in array " ) ;
/* Update values and total result size */
/* Update total result size */
if ( typbyval )
if ( typbyval )
{
values [ i ] = p ;
nbytes + = typlen ;
nbytes + = typlen ;
}
else
else
{
nbytes + = ( ( typlen > 0 ) ? typlen :
int len ;
INTALIGN ( VARSIZE ( DatumGetPointer ( values [ i ] ) ) ) ) ;
len = ( ( typlen > 0 ) ? typlen : INTALIGN ( * ( int32 * ) p ) ) ;
/* Needed because _CopyArrayEls tries to pfree items */
if ( p = = elt )
{
p = ( char * ) palloc ( len ) ;
memcpy ( p , elt , len ) ;
}
values [ i ] = p ;
nbytes + = len ;
}
}
}
/* Allocate and initialize the result array */
/* Allocate and initialize the result array */
@ -1442,18 +1441,130 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
result = ( ArrayType * ) palloc ( nbytes ) ;
result = ( ArrayType * ) palloc ( nbytes ) ;
MemSet ( result , 0 , nbytes ) ;
MemSet ( result , 0 , nbytes ) ;
memcpy ( ( char * ) result , ( char * ) & nbytes , sizeof ( int ) ) ;
result - > size = nbytes ;
memcpy ( ( char * ) ARR_NDIM_PTR ( result ) , ( char * ) & ndim , sizeof ( int ) ) ;
result - > ndim = ndim ;
memcpy ( ( char * ) ARR_DIMS ( result ) , ARR_DIMS ( v ) , 2 * ndim * sizeof ( int ) ) ;
memcpy ( ARR_DIMS ( result ) , ARR_DIMS ( v ) , 2 * ndim * sizeof ( int ) ) ;
/* Copy new values into the result array. values is pfreed. */
/* Note: do not risk trying to pfree the results of the called function */
_ CopyArrayEls( ( char * * ) value s,
CopyArrayEls ( ARR_DATA_PTR ( result ) , values , nitem s,
ARR_DATA_PTR ( result ) , nitems ,
typbyval , typlen , typalign , false ) ;
typlen , typalign , typbyval ) ;
pfree ( values ) ;
PG_RETURN_POINTER ( result ) ;
PG_RETURN_ARRAYTYPE_P ( result ) ;
}
}
/*----------
* construct_array - - - simple method for constructing an array object
*
* elems : array of Datum items to become the array contents
* nelems : number of items
* elmbyval , elmlen , elmalign : info for the datatype of the items
*
* A palloc ' d 1 - D array object is constructed and returned . Note that
* elem values will be copied into the object even if pass - by - ref type .
* NULL element values are not supported .
* - - - - - - - - - -
*/
ArrayType *
construct_array ( Datum * elems , int nelems ,
bool elmbyval , int elmlen , char elmalign )
{
ArrayType * result ;
int nbytes ;
int i ;
if ( elmlen > 0 )
{
/* XXX what about alignment? */
nbytes = elmlen * nelems ;
}
else
{
/* varlena type */
nbytes = 0 ;
for ( i = 0 ; i < nelems ; i + + )
nbytes + = INTALIGN ( VARSIZE ( DatumGetPointer ( elems [ i ] ) ) ) ;
}
/* Allocate and initialize 1-D result array */
nbytes + = ARR_OVERHEAD ( 1 ) ;
result = ( ArrayType * ) palloc ( nbytes ) ;
result - > size = nbytes ;
result - > ndim = 1 ;
result - > flags = 0 ;
ARR_DIMS ( result ) [ 0 ] = nelems ;
ARR_LBOUND ( result ) [ 0 ] = 1 ;
CopyArrayEls ( ARR_DATA_PTR ( result ) , elems , nelems ,
elmbyval , elmlen , elmalign , false ) ;
return result ;
}
/*----------
* deconstruct_array - - - simple method for extracting data from an array
*
* array : array object to examine ( must not be NULL )
* elmbyval , elmlen , elmalign : info for the datatype of the items
* elemsp : return value , set to point to palloc ' d array of Datum values
* nelemsp : return value , set to number of extracted values
*
* If array elements are pass - by - ref data type , the returned Datums will
* be pointers into the array object .
* - - - - - - - - - -
*/
void
deconstruct_array ( ArrayType * array ,
bool elmbyval , int elmlen , char elmalign ,
Datum * * elemsp , int * nelemsp )
{
Datum * elems ;
int nelems ;
char * p ;
int i ;
nelems = getNitems ( ARR_NDIM ( array ) , ARR_DIMS ( array ) ) ;
if ( nelems < = 0 )
{
* elemsp = NULL ;
* nelemsp = 0 ;
return ;
}
* elemsp = elems = ( Datum * ) palloc ( nelems * sizeof ( Datum ) ) ;
* nelemsp = nelems ;
p = ARR_DATA_PTR ( array ) ;
for ( i = 0 ; i < nelems ; i + + )
{
if ( elmbyval )
{
switch ( elmlen )
{
case 1 :
elems [ i ] = CharGetDatum ( * p ) ;
break ;
case 2 :
elems [ i ] = Int16GetDatum ( * ( int16 * ) p ) ;
break ;
case 4 :
elems [ i ] = Int32GetDatum ( * ( int32 * ) p ) ;
break ;
}
p + = elmlen ;
}
else
{
elems [ i ] = PointerGetDatum ( p ) ;
if ( elmlen > 0 )
p + = elmlen ;
else
p + = INTALIGN ( VARSIZE ( p ) ) ;
}
}
}
/*-----------------------------------------------------------------------------
/*-----------------------------------------------------------------------------
* array_eq :
* array_eq :
* compares two arrays for equality
* compares two arrays for equality
@ -1464,8 +1575,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
Datum
Datum
array_eq ( PG_FUNCTION_ARGS )
array_eq ( PG_FUNCTION_ARGS )
{
{
ArrayType * array1 = ( ArrayType * ) PG_GETARG_VARLENA _P( 0 ) ;
ArrayType * array1 = PG_GETARG_ARRAYTYPE _P( 0 ) ;
ArrayType * array2 = ( ArrayType * ) PG_GETARG_VARLENA _P( 1 ) ;
ArrayType * array2 = PG_GETARG_ARRAYTYPE _P( 1 ) ;
if ( * ( int32 * ) array1 ! = * ( int32 * ) array2 )
if ( * ( int32 * ) array1 ! = * ( int32 * ) array2 )
PG_RETURN_BOOL ( false ) ;
PG_RETURN_BOOL ( false ) ;
@ -1493,14 +1604,11 @@ system_cache_lookup(Oid element_type,
typeTuple = SearchSysCacheTuple ( TYPEOID ,
typeTuple = SearchSysCacheTuple ( TYPEOID ,
ObjectIdGetDatum ( element_type ) ,
ObjectIdGetDatum ( element_type ) ,
0 , 0 , 0 ) ;
0 , 0 , 0 ) ;
if ( ! HeapTupleIsValid ( typeTuple ) )
if ( ! HeapTupleIsValid ( typeTuple ) )
{
elog ( ERROR , " array_out: Cache lookup failed for type %u " ,
elog ( ERROR , " array_out: Cache lookup failed for type %u \n " ,
element_type ) ;
element_type ) ;
return ;
}
typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTuple ) ;
typeStruct = ( Form_pg_type ) GETSTRUCT ( typeTuple ) ;
* typlen = typeStruct - > typlen ;
* typlen = typeStruct - > typlen ;
* typbyval = typeStruct - > typbyval ;
* typbyval = typeStruct - > typbyval ;
* typdelim = typeStruct - > typdelim ;
* typdelim = typeStruct - > typdelim ;
@ -1536,7 +1644,11 @@ _ArrayCast(char *value, bool byval, int len)
return 0 ;
return 0 ;
}
}
/*
* Copy datum to * dest and return total space used ( including align padding )
*
* XXX this routine needs to be told typalign too !
*/
static int
static int
ArrayCastAndSet ( Datum src ,
ArrayCastAndSet ( Datum src ,
bool typbyval ,
bool typbyval ,
@ -1560,16 +1672,26 @@ ArrayCastAndSet(Datum src,
case 4 :
case 4 :
* ( int32 * ) dest = DatumGetInt32 ( src ) ;
* ( int32 * ) dest = DatumGetInt32 ( src ) ;
break ;
break ;
default :
elog ( ERROR , " ArrayCastAndSet: unexpected typlen " ) ;
break ;
}
}
/* For by-val types, assume no alignment padding is needed */
inc = typlen ;
}
}
else
else
{
memmove ( dest , DatumGetPointer ( src ) , typlen ) ;
memmove ( dest , DatumGetPointer ( src ) , typlen ) ;
inc = typlen ;
/* XXX WRONG: need to consider type's alignment requirement */
inc = typlen ;
}
}
}
else
else
{
{
memmove ( dest , DatumGetPointer ( src ) , * ( int32 * ) DatumGetPointer ( src ) ) ;
/* varlena type */
inc = ( INTALIGN ( * ( int32 * ) DatumGetPointer ( src ) ) ) ;
memmove ( dest , DatumGetPointer ( src ) , VARSIZE ( DatumGetPointer ( src ) ) ) ;
/* XXX WRONG: should use MAXALIGN or type's alignment requirement */
inc = INTALIGN ( VARSIZE ( DatumGetPointer ( src ) ) ) ;
}
}
return inc ;
return inc ;
}
}