88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.52 2000/01/26 05:57:12 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.53 2000/05/29 21:02:32 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
1717
1818#include "postgres.h"
1919
20-
2120#include "catalog/catalog.h"
2221#include "catalog/pg_type.h"
2322#include "fmgr.h"
@@ -1277,19 +1276,33 @@ array_assgn(ArrayType *array,
12771276/*
12781277 * array_map()
12791278 *
1280- * Map an arbitrary function to an array and return a new array with
1281- * same dimensions and the source elements transformed by fn().
1279+ * Map an array through an arbitrary function. Return a new array with
1280+ * same dimensions and each source element transformed by fn(). Each
1281+ * source element is passed as the first argument to fn(); additional
1282+ * arguments to be passed to fn() can be specified by the caller.
1283+ * The output array can have a different element type than the input.
1284+ *
1285+ * Parameters are:
1286+ * * fcinfo: a function-call data structure pre-constructed by the caller
1287+ * to be ready to call the desired function, with everything except the
1288+ * first argument position filled in. In particular, flinfo identifies
1289+ * the function fn(), and if nargs > 1 then argument positions after the
1290+ * first must be preset to the additional values to be passed. The
1291+ * first argument position initially holds the input array value.
1292+ * * inpType: OID of element type of input array. This must be the same as,
1293+ * or binary-compatible with, the first argument type of fn().
1294+ * * retType: OID of element type of output array. This must be the same as,
1295+ * or binary-compatible with, the result type of fn().
1296+ *
1297+ * NB: caller must assure that input array is not NULL. Currently,
1298+ * any additional parameters passed to fn() may not be specified as NULL
1299+ * either.
12821300 */
1283- ArrayType *
1284- array_map (ArrayType * v ,
1285- Oid type ,
1286- char * (* fn ) (),
1287- Oid retType ,
1288- int nargs ,
1289- ...)
1301+ Datum
1302+ array_map (FunctionCallInfo fcinfo ,Oid inpType ,Oid retType )
12901303{
1304+ ArrayType * v ;
12911305ArrayType * result ;
1292- void * args [4 ];
12931306char * * values ;
12941307char * elt ;
12951308int * dim ;
@@ -1307,35 +1320,31 @@ array_map(ArrayType *v,
13071320char typalign ;
13081321char * s ;
13091322char * p ;
1310- va_list ap ;
1323+
1324+ /* Get input array */
1325+ if (fcinfo -> nargs < 1 )
1326+ elog (ERROR ,"array_map: invalid nargs: %d" ,fcinfo -> nargs );
1327+ if (PG_ARGISNULL (0 ))
1328+ elog (ERROR ,"array_map: null input array" );
1329+ v = (ArrayType * )PG_GETARG_POINTER (0 );
13111330
13121331/* Large objects not yet supported */
13131332if (ARR_IS_LO (v )== true)
13141333elog (ERROR ,"array_map: large objects not supported" );
13151334
1316- /* Check nargs */
1317- if ((nargs < 0 )|| (nargs > 4 ))
1318- elog (ERROR ,"array_map: invalid nargs: %d" ,nargs );
1319-
1320- /* Copy extra args to local variable */
1321- va_start (ap ,nargs );
1322- for (i = 0 ;i < nargs ;i ++ )
1323- args [i ]= (void * )va_arg (ap ,char * );
1324- va_end (ap );
1325-
1326- /* Lookup source and result types. Unneeded variables are reused. */
1327- system_cache_lookup (type , false,& inp_typlen ,& inp_typbyval ,
1328- & typdelim ,& typelem ,& proc ,& typalign );
1329- system_cache_lookup (retType , false,& typlen ,& typbyval ,
1330- & typdelim ,& typelem ,& proc ,& typalign );
1331-
13321335ndim = ARR_NDIM (v );
13331336dim = ARR_DIMS (v );
13341337nitems = getNitems (ndim ,dim );
13351338
13361339/* Check for empty array */
13371340if (nitems <=0 )
1338- return v ;
1341+ PG_RETURN_POINTER (v );
1342+
1343+ /* Lookup source and result types. Unneeded variables are reused. */
1344+ system_cache_lookup (inpType , false,& inp_typlen ,& inp_typbyval ,
1345+ & typdelim ,& typelem ,& proc ,& typalign );
1346+ system_cache_lookup (retType , false,& typlen ,& typbyval ,
1347+ & typdelim ,& typelem ,& proc ,& typalign );
13391348
13401349/* Allocate temporary array for new values */
13411350values = (char * * )palloc (nitems * sizeof (char * ));
@@ -1374,33 +1383,23 @@ array_map(ArrayType *v,
13741383}
13751384
13761385/*
1377- * Apply the given function to source elt and extra args. nargs is
1378- * the number of extra args taken by fn().
1386+ * Apply the given function to source elt and extra args.
1387+ *
1388+ * We assume the extra args are non-NULL, so need not check
1389+ * whether fn() is strict. Would need to do more work here
1390+ * to support arrays containing nulls, too.
13791391 */
1380- switch (nargs )
1381- {
1382- case 0 :
1383- p = (char * ) (* fn ) (elt );
1384- break ;
1385- case 1 :
1386- p = (char * ) (* fn ) (elt ,args [0 ]);
1387- break ;
1388- case 2 :
1389- p = (char * ) (* fn ) (elt ,args [0 ],args [1 ]);
1390- break ;
1391- case 3 :
1392- p = (char * ) (* fn ) (elt ,args [0 ],args [1 ],args [2 ]);
1393- break ;
1394- case 4 :
1395- default :
1396- p = (char * ) (* fn ) (elt ,args [0 ],args [1 ],args [2 ],args [3 ]);
1397- break ;
1398- }
1392+ fcinfo -> arg [0 ]= (Datum )elt ;
1393+ fcinfo -> argnull [0 ]= false;
1394+ fcinfo -> isnull = false;
1395+ p = (char * )FunctionCallInvoke (fcinfo );
1396+ if (fcinfo -> isnull )
1397+ elog (ERROR ,"array_map: cannot handle NULL in array" );
13991398
14001399/* Update values and total result size */
14011400if (typbyval )
14021401{
1403- values [i ]= ( char * ) p ;
1402+ values [i ]= p ;
14041403nbytes += typlen ;
14051404}
14061405else
@@ -1414,7 +1413,7 @@ array_map(ArrayType *v,
14141413p = (char * )palloc (len );
14151414memcpy (p ,elt ,len );
14161415}
1417- values [i ]= ( char * ) p ;
1416+ values [i ]= p ;
14181417nbytes += len ;
14191418}
14201419}
@@ -1433,7 +1432,7 @@ array_map(ArrayType *v,
14331432ARR_DATA_PTR (result ),nitems ,
14341433typlen ,typalign ,typbyval );
14351434
1436- return result ;
1435+ PG_RETURN_POINTER ( result ) ;
14371436}
14381437
14391438/*-----------------------------------------------------------------------------