@ -90,14 +90,15 @@ typedef struct ArrayIteratorData
} ArrayIteratorData ;
static bool array_isspace ( char ch ) ;
static int ArrayCount ( const char * str , int * dim , char typdelim ) ;
static void ReadArrayStr ( char * arrayStr , const char * origStr ,
static int ArrayCount ( const char * str , int * dim , char typdelim ,
Node * escontext ) ;
static bool ReadArrayStr ( char * arrayStr , const char * origStr ,
int nitems , int ndim , int * dim ,
FmgrInfo * inputproc , Oid typioparam , int32 typmod ,
char typdelim ,
int typlen , bool typbyval , char typalign ,
Datum * values , bool * nulls ,
bool * hasnulls , int32 * nbytes ) ;
bool * hasnulls , int32 * nbytes , Node * escontext ) ;
static void ReadArrayBinary ( StringInfo buf , int nitems ,
FmgrInfo * receiveproc , Oid typioparam , int32 typmod ,
int typlen , bool typbyval , char typalign ,
@ -177,6 +178,7 @@ array_in(PG_FUNCTION_ARGS)
Oid element_type = PG_GETARG_OID ( 1 ) ; /* type of an array
* element */
int32 typmod = PG_GETARG_INT32 ( 2 ) ; /* typmod for array elements */
Node * escontext = fcinfo - > context ;
int typlen ;
bool typbyval ;
char typalign ;
@ -258,7 +260,7 @@ array_in(PG_FUNCTION_ARGS)
break ; /* no more dimension items */
p + + ;
if ( ndim > = MAXDIM )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_PROGRAM_LIMIT_EXCEEDED ) ,
errmsg ( " number of array dimensions (%d) exceeds the maximum allowed (%d) " ,
ndim + 1 , MAXDIM ) ) ) ;
@ -266,7 +268,7 @@ array_in(PG_FUNCTION_ARGS)
for ( q = p ; isdigit ( ( unsigned char ) * q ) | | ( * q = = ' - ' ) | | ( * q = = ' + ' ) ; q + + )
/* skip */ ;
if ( q = = p ) /* no digits? */
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " \" [ \" must introduce explicitly-specified array dimensions. " ) ) ) ;
@ -280,7 +282,7 @@ array_in(PG_FUNCTION_ARGS)
for ( q = p ; isdigit ( ( unsigned char ) * q ) | | ( * q = = ' - ' ) | | ( * q = = ' + ' ) ; q + + )
/* skip */ ;
if ( q = = p ) /* no digits? */
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Missing array dimension value. " ) ) ) ;
@ -291,7 +293,7 @@ array_in(PG_FUNCTION_ARGS)
lBound [ ndim ] = 1 ;
}
if ( * q ! = ' ] ' )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Missing \" %s \" after array dimensions. " ,
@ -301,7 +303,7 @@ array_in(PG_FUNCTION_ARGS)
ub = atoi ( p ) ;
p = q + 1 ;
if ( ub < lBound [ ndim ] )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_ARRAY_SUBSCRIPT_ERROR ) ,
errmsg ( " upper bound cannot be less than lower bound " ) ) ) ;
@ -313,11 +315,13 @@ array_in(PG_FUNCTION_ARGS)
{
/* No array dimensions, so intuit dimensions from brace structure */
if ( * p ! = ' { ' )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Array value must start with \" { \" or dimension information. " ) ) ) ;
ndim = ArrayCount ( p , dim , typdelim ) ;
ndim = ArrayCount ( p , dim , typdelim , escontext ) ;
if ( ndim < 0 )
PG_RETURN_NULL ( ) ;
for ( i = 0 ; i < ndim ; i + + )
lBound [ i ] = 1 ;
}
@ -328,7 +332,7 @@ array_in(PG_FUNCTION_ARGS)
/* If array dimensions are given, expect '=' operator */
if ( strncmp ( p , ASSGN , strlen ( ASSGN ) ) ! = 0 )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Missing \" %s \" after array dimensions. " ,
@ -342,20 +346,22 @@ array_in(PG_FUNCTION_ARGS)
* were given
*/
if ( * p ! = ' { ' )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Array contents must start with \" { \" . " ) ) ) ;
ndim_braces = ArrayCount ( p , dim_braces , typdelim ) ;
ndim_braces = ArrayCount ( p , dim_braces , typdelim , escontext ) ;
if ( ndim_braces < 0 )
PG_RETURN_NULL ( ) ;
if ( ndim_braces ! = ndim )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Specified array dimensions do not match array contents. " ) ) ) ;
for ( i = 0 ; i < ndim ; + + i )
{
if ( dim [ i ] ! = dim_braces [ i ] )
ereport ( ERROR ,
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , string ) ,
errdetail ( " Specified array dimensions do not match array contents. " ) ) ) ;
@ -372,8 +378,11 @@ array_in(PG_FUNCTION_ARGS)
# endif
/* This checks for overflow of the array dimensions */
nitems = ArrayGetNItems ( ndim , dim ) ;
ArrayCheckBounds ( ndim , dim , lBound ) ;
nitems = ArrayGetNItemsSafe ( ndim , dim , escontext ) ;
if ( nitems < 0 )
PG_RETURN_NULL ( ) ;
if ( ! ArrayCheckBoundsSafe ( ndim , dim , lBound , escontext ) )
PG_RETURN_NULL ( ) ;
/* Empty array? */
if ( nitems = = 0 )
@ -381,13 +390,14 @@ array_in(PG_FUNCTION_ARGS)
dataPtr = ( Datum * ) palloc ( nitems * sizeof ( Datum ) ) ;
nullsPtr = ( bool * ) palloc ( nitems * sizeof ( bool ) ) ;
ReadArrayStr ( p , string ,
nitems , ndim , dim ,
& my_extra - > proc , typioparam , typmod ,
typdelim ,
typlen , typbyval , typalign ,
dataPtr , nullsPtr ,
& hasnulls , & nbytes ) ;
if ( ! ReadArrayStr ( p , string ,
nitems , ndim , dim ,
& my_extra - > proc , typioparam , typmod ,
typdelim ,
typlen , typbyval , typalign ,
dataPtr , nullsPtr ,
& hasnulls , & nbytes , escontext ) )
PG_RETURN_NULL ( ) ;
if ( hasnulls )
{
dataoffset = ARR_OVERHEAD_WITHNULLS ( ndim , nitems ) ;
@ -451,9 +461,12 @@ array_isspace(char ch)
*
* Returns number of dimensions as function result . The axis lengths are
* returned in dim [ ] , which must be of size MAXDIM .
*
* If we detect an error , fill * escontext with error details and return - 1
* ( unless escontext isn ' t provided , in which case errors will be thrown ) .
*/
static int
ArrayCount ( const char * str , int * dim , char typdelim )
ArrayCount ( const char * str , int * dim , char typdelim , Node * escontext )
{
int nest_level = 0 ,
i ;
@ -488,11 +501,10 @@ ArrayCount(const char *str, int *dim, char typdelim)
{
case ' \0 ' :
/* Signal a premature end of the string */
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected end of input. " ) ) ) ;
break ;
case ' \\ ' :
/*
@ -504,7 +516,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state ! = ARRAY_ELEM_STARTED & &
parse_state ! = ARRAY_QUOTED_ELEM_STARTED & &
parse_state ! = ARRAY_ELEM_DELIMITED )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected \" %c \" character. " ,
@ -515,7 +527,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if ( * ( ptr + 1 ) )
ptr + + ;
else
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected end of input. " ) ) ) ;
@ -530,7 +542,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if ( parse_state ! = ARRAY_LEVEL_STARTED & &
parse_state ! = ARRAY_QUOTED_ELEM_STARTED & &
parse_state ! = ARRAY_ELEM_DELIMITED )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected array element. " ) ) ) ;
@ -551,14 +563,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
if ( parse_state ! = ARRAY_NO_LEVEL & &
parse_state ! = ARRAY_LEVEL_STARTED & &
parse_state ! = ARRAY_LEVEL_DELIMITED )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected \" %c \" character. " ,
' { ' ) ) ) ;
parse_state = ARRAY_LEVEL_STARTED ;
if ( nest_level > = MAXDIM )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_PROGRAM_LIMIT_EXCEEDED ) ,
errmsg ( " number of array dimensions (%d) exceeds the maximum allowed (%d) " ,
nest_level + 1 , MAXDIM ) ) ) ;
@ -581,14 +593,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state ! = ARRAY_QUOTED_ELEM_COMPLETED & &
parse_state ! = ARRAY_LEVEL_COMPLETED & &
! ( nest_level = = 1 & & parse_state = = ARRAY_LEVEL_STARTED ) )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected \" %c \" character. " ,
' } ' ) ) ) ;
parse_state = ARRAY_LEVEL_COMPLETED ;
if ( nest_level = = 0 )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unmatched \" %c \" character. " , ' } ' ) ) ) ;
@ -596,7 +608,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if ( nelems_last [ nest_level ] ! = 0 & &
nelems [ nest_level ] ! = nelems_last [ nest_level ] )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Multidimensional arrays must have "
@ -630,7 +642,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state ! = ARRAY_ELEM_COMPLETED & &
parse_state ! = ARRAY_QUOTED_ELEM_COMPLETED & &
parse_state ! = ARRAY_LEVEL_COMPLETED )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected \" %c \" character. " ,
@ -653,7 +665,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if ( parse_state ! = ARRAY_LEVEL_STARTED & &
parse_state ! = ARRAY_ELEM_STARTED & &
parse_state ! = ARRAY_ELEM_DELIMITED )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Unexpected array element. " ) ) ) ;
@ -673,7 +685,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
while ( * ptr )
{
if ( ! array_isspace ( * ptr + + ) )
ereport ( ERROR ,
ereturn ( escontext , - 1 ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " , str ) ,
errdetail ( " Junk after closing right brace. " ) ) ) ;
@ -713,11 +725,16 @@ ArrayCount(const char *str, int *dim, char typdelim)
* * hasnulls : set true iff there are any null elements .
* * nbytes : set to total size of data area needed ( including alignment
* padding but not including array header overhead ) .
* * escontext : if this points to an ErrorSaveContext , details of
* any error are reported there .
*
* Result :
* true for success , false for failure ( if escontext is provided ) .
*
* Note that values [ ] and nulls [ ] are allocated by the caller , and must have
* nitems elements .
*/
static void
static bool
ReadArrayStr ( char * arrayStr ,
const char * origStr ,
int nitems ,
@ -733,7 +750,8 @@ ReadArrayStr(char *arrayStr,
Datum * values ,
bool * nulls ,
bool * hasnulls ,
int32 * nbytes )
int32 * nbytes ,
Node * escontext )
{
int i ,
nest_level = 0 ;
@ -784,7 +802,7 @@ ReadArrayStr(char *arrayStr,
{
case ' \0 ' :
/* Signal a premature end of the string */
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " ,
origStr ) ) ) ;
@ -793,7 +811,7 @@ ReadArrayStr(char *arrayStr,
/* Skip backslash, copy next character as-is. */
srcptr + + ;
if ( * srcptr = = ' \0 ' )
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " ,
origStr ) ) ) ;
@ -823,7 +841,7 @@ ReadArrayStr(char *arrayStr,
if ( ! in_quotes )
{
if ( nest_level > = ndim )
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " ,
origStr ) ) ) ;
@ -838,7 +856,7 @@ ReadArrayStr(char *arrayStr,
if ( ! in_quotes )
{
if ( nest_level = = 0 )
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " ,
origStr ) ) ) ;
@ -891,7 +909,7 @@ ReadArrayStr(char *arrayStr,
* dstendptr = ' \0 ' ;
if ( i < 0 | | i > = nitems )
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_INVALID_TEXT_REPRESENTATION ) ,
errmsg ( " malformed array literal: \" %s \" " ,
origStr ) ) ) ;
@ -900,14 +918,20 @@ ReadArrayStr(char *arrayStr,
pg_strcasecmp ( itemstart , " NULL " ) = = 0 )
{
/* it's a NULL item */
values [ i ] = InputFunctionCall ( inputproc , NULL ,
typioparam , typmod ) ;
if ( ! InputFunctionCallSafe ( inputproc , NULL ,
typioparam , typmod ,
escontext ,
& values [ i ] ) )
return false ;
nulls [ i ] = true ;
}
else
{
values [ i ] = InputFunctionCall ( inputproc , itemstart ,
typioparam , typmod ) ;
if ( ! InputFunctionCallSafe ( inputproc , itemstart ,
typioparam , typmod ,
escontext ,
& values [ i ] ) )
return false ;
nulls [ i ] = false ;
}
}
@ -930,7 +954,7 @@ ReadArrayStr(char *arrayStr,
totbytes = att_align_nominal ( totbytes , typalign ) ;
/* check for overflow of total request */
if ( ! AllocSizeIsValid ( totbytes ) )
ereport ( ERROR ,
ereturn ( escontext , false ,
( errcode ( ERRCODE_PROGRAM_LIMIT_EXCEEDED ) ,
errmsg ( " array size exceeds the maximum allowed (%d) " ,
( int ) MaxAllocSize ) ) ) ;
@ -938,6 +962,7 @@ ReadArrayStr(char *arrayStr,
}
* hasnulls = hasnull ;
* nbytes = totbytes ;
return true ;
}