]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/arrayfuncs.c
I had overlooked the fact that some fmgr-callable functions return void
[postgresql] / src / backend / utils / adt / arrayfuncs.c
index 8e09385ba4f79af82bc0d59f26237a84bc99d37f..aae18aa047fc464691589be7b2911d844a43f847 100644 (file)
@@ -3,23 +3,20 @@
  * arrayfuncs.c
  *       Special functions for arrays.
  *
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.46 1999/07/16 05:00:00 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.58 2000/06/14 05:24:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
 
 #include "postgres.h"
 
-
 #include "catalog/catalog.h"
 #include "catalog/pg_type.h"
 #include "fmgr.h"
@@ -71,7 +68,7 @@ static void _LOArrayRange(int *st, int *endp, int bsize, int srcfd,
                          int destfd, ArrayType *array, int isSrcLO, bool *isNull);
 static void _ReadArray(int *st, int *endp, int bsize, int srcfd, int destfd,
                   ArrayType *array, int isDestLO, bool *isNull);
-static int     ArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest);
+static int     ArrayCastAndSet(Datum src, bool typbyval, int typlen, char *dest);
 static int     SanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx);
 static int     array_read(char *destptr, int eltsize, int nitems, char *srcptr);
 static char *array_seek(char *ptr, int eltsize, int nitems);
@@ -79,16 +76,17 @@ static char *array_seek(char *ptr, int eltsize, int nitems);
 /*---------------------------------------------------------------------
  * array_in :
  *               converts an array from the external format in "string" to
- *               it internal format.
+ *               its internal format.
  * return value :
  *               the internal representation of the input array
  *--------------------------------------------------------------------
  */
-char *
-array_in(char *string,                 /* input array in external form */
-                Oid element_type,              /* type OID of an array element */
-                int32 typmod)
+Datum
+array_in(PG_FUNCTION_ARGS)
 {
+       char       *string = PG_GETARG_CSTRING(0); /* external form */
+       Oid                     element_type = PG_GETARG_OID(1); /* type of an array element */
+       int32           typmod = PG_GETARG_INT32(2); /* typmod for array elements */
        int                     typlen;
        bool            typbyval,
                                done;
@@ -104,7 +102,7 @@ array_in(char *string,                      /* input array in external form */
                                nitems;
        int32           nbytes;
        char       *dataPtr;
-       ArrayType  *retval = NULL;
+       ArrayType  *retval;
        int                     ndim,
                                dim[MAXDIM],
                                lBound[MAXDIM];
@@ -186,11 +184,10 @@ array_in(char *string,                    /* input array in external form */
        nitems = getNitems(ndim, dim);
        if (nitems == 0)
        {
-               char       *emptyArray = palloc(sizeof(ArrayType));
-
-               MemSet(emptyArray, 0, sizeof(ArrayType));
-               *(int32 *) emptyArray = sizeof(ArrayType);
-               return emptyArray;
+               retval = (ArrayType *) palloc(sizeof(ArrayType));
+               MemSet(retval, 0, sizeof(ArrayType));
+               *(int32 *) retval = sizeof(ArrayType);
+               PG_RETURN_POINTER(retval);
        }
 
        if (*p == '{')
@@ -238,9 +235,10 @@ array_in(char *string,                     /* input array in external form */
                memmove(ARR_DATA_PTR(retval), dataPtr, bytes);
 #endif
                elog(ERROR, "large object arrays not supported");
+               PG_RETURN_NULL();
        }
        pfree(string_save);
-       return (char *) retval;
+       PG_RETURN_POINTER(retval);
 }
 
 /*-----------------------------------------------------------------------------
@@ -444,7 +442,10 @@ _ReadArrayStr(char *arrayStr,
                *q = '\0';
                if (i >= nitems)
                        elog(ERROR, "array_in: illformed array constant");
-               values[i] = (*fmgr_faddr(inputproc)) (p, typelem, typmod);
+               values[i] = (char *) FunctionCall3(inputproc,
+                                                                                  CStringGetDatum(p),
+                                                                                  ObjectIdGetDatum(typelem),
+                                                                                  Int32GetDatum(typmod));
                p = ++q;
                if (!eoArray)
 
@@ -475,7 +476,7 @@ _ReadArrayStr(char *arrayStr,
                        if (values[i])
                        {
                                if (typalign == 'd')
-                                       *nbytes += DOUBLEALIGN(*(int32 *) values[i]);
+                                       *nbytes += MAXALIGN(*(int32 *) values[i]);
                                else
                                        *nbytes += INTALIGN(*(int32 *) values[i]);
                        }
@@ -538,8 +539,11 @@ _ReadLOArray(char *str,
 
        if (inputfile == NULL)
                elog(ERROR, "array_in: missing file name");
-       lobjId = lo_creat(0);
-       *fd = lo_open(lobjId, INV_READ);
+       lobjId = DatumGetObjectId(DirectFunctionCall1(lo_creat,
+                                                                                                 Int32GetDatum(0)));
+       *fd = DatumGetInt32(DirectFunctionCall2(lo_open,
+                                                                                       ObjectIdGetDatum(lobjId),
+                                                                                       Int32GetDatum(INV_READ)));
        if (*fd < 0)
                elog(ERROR, "Large object create failed");
        retStr = inputfile;
@@ -549,11 +553,7 @@ _ReadLOArray(char *str,
        {
                FILE       *afd;
 
-#ifndef __CYGWIN32__
-               if ((afd = AllocateFile(accessfile, "r")) == NULL)
-#else
-               if ((afd = AllocateFile(accessfile, "r")) == NULL)
-#endif
+               if ((afd = AllocateFile(accessfile, PG_BINARY_R)) == NULL)
                        elog(ERROR, "unable to open access pattern file");
                *chunkFlag = true;
                retStr = _ChunkArray(*fd, afd, ndim, dim, baseSize, nbytes,
@@ -579,7 +579,7 @@ _CopyArrayEls(char **values,
        {
                int                     inc;
 
-               inc = ArrayCastAndSet(values[i], typbyval, typlen, p);
+               inc = ArrayCastAndSet((Datum) values[i], typbyval, typlen, p);
                p += inc;
                if (!typbyval)
                        pfree(values[i]);
@@ -593,9 +593,11 @@ _CopyArrayEls(char **values,
  *               containing the array in its external format.
  *-------------------------------------------------------------------------
  */
-char *
-array_out(ArrayType *v, Oid element_type)
+Datum
+array_out(PG_FUNCTION_ARGS)
 {
+       ArrayType  *v = (ArrayType *) PG_GETARG_VARLENA_P(0);
+       Oid                     element_type = PG_GETARG_OID(1);
        int                     typlen;
        bool            typbyval;
        char            typdelim;
@@ -603,7 +605,6 @@ array_out(ArrayType *v, Oid element_type)
                                typelem;
        FmgrInfo        outputproc;
        char            typalign;
-
        char       *p,
                           *tmp,
                           *retval,
@@ -618,30 +619,28 @@ array_out(ArrayType *v, Oid element_type)
                                l,
 #endif
                                indx[MAXDIM];
-       bool            dummy_bool;
        int                     ndim,
                           *dim;
 
-       if (v == (ArrayType *) NULL)
-               return (char *) NULL;
-
        if (ARR_IS_LO(v) == true)
        {
-               char       *p,
-                                  *save_p;
-               int                     nbytes;
+               text       *p;
+               int                     plen,
+                                       nbytes;
 
-               /* get a wide string to print to */
-               p = array_dims(v, &dummy_bool);
-               nbytes = strlen(ARR_DATA_PTR(v)) + VARHDRSZ + *(int *) p;
+               p = (text *) DatumGetPointer(DirectFunctionCall1(array_dims,
+                                                                                                                PointerGetDatum(v)));
+               plen = VARSIZE(p) - VARHDRSZ;
 
-               save_p = (char *) palloc(nbytes);
+               /* get a wide string to print to */
+               nbytes = strlen(ARR_DATA_PTR(v)) + strlen(ASSGN) + plen + 1;
+               retval = (char *) palloc(nbytes);
 
-               strcpy(save_p, p + sizeof(int));
-               strcat(save_p, ASSGN);
-               strcat(save_p, ARR_DATA_PTR(v));
+               memcpy(retval, VARDATA(p), plen);
+               strcpy(retval + plen, ASSGN);
+               strcat(retval, ARR_DATA_PTR(v));
                pfree(p);
-               return save_p;
+               PG_RETURN_CSTRING(retval);
        }
 
        system_cache_lookup(element_type, false, &typlen, &typbyval,
@@ -654,12 +653,11 @@ array_out(ArrayType *v, Oid element_type)
 
        if (nitems == 0)
        {
-               char       *emptyArray = palloc(3);
-
-               emptyArray[0] = '{';
-               emptyArray[1] = '}';
-               emptyArray[2] = '\0';
-               return emptyArray;
+               retval = (char *) palloc(3);
+               retval[0] = '{';
+               retval[1] = '}';
+               retval[2] = '\0';
+               PG_RETURN_CSTRING(retval);
        }
 
        p = ARR_DATA_PTR(v);
@@ -672,21 +670,33 @@ array_out(ArrayType *v, Oid element_type)
                        switch (typlen)
                        {
                                case 1:
-                                       values[i] = (*fmgr_faddr(&outputproc)) (*p, typelem);
+                                       values[i] = DatumGetCString(FunctionCall3(&outputproc,
+                                                                                               CharGetDatum(*p),
+                                                                                               ObjectIdGetDatum(typelem),
+                                                                                               Int32GetDatum(-1)));
                                        break;
                                case 2:
-                                       values[i] = (*fmgr_faddr(&outputproc)) (*(int16 *) p, typelem);
+                                       values[i] = DatumGetCString(FunctionCall3(&outputproc,
+                                                                                               Int16GetDatum(*(int16 *) p),
+                                                                                               ObjectIdGetDatum(typelem),
+                                                                                               Int32GetDatum(-1)));
                                        break;
                                case 3:
                                case 4:
-                                       values[i] = (*fmgr_faddr(&outputproc)) (*(int32 *) p, typelem);
+                                       values[i] = DatumGetCString(FunctionCall3(&outputproc,
+                                                                                               Int32GetDatum(*(int32 *) p),
+                                                                                               ObjectIdGetDatum(typelem),
+                                                                                               Int32GetDatum(-1)));
                                        break;
                        }
                        p += typlen;
                }
                else
                {
-                       values[i] = (*fmgr_faddr(&outputproc)) (p, typelem);
+                       values[i] = DatumGetCString(FunctionCall3(&outputproc,
+                                                                                               PointerGetDatum(p),
+                                                                                               ObjectIdGetDatum(typelem),
+                                                                                               Int32GetDatum(-1)));
                        if (typlen > 0)
                                p += typlen;
                        else
@@ -765,58 +775,61 @@ array_out(ArrayType *v, Oid element_type)
        } while (j != -1);
 
        pfree(values);
-       return retval;
+       PG_RETURN_CSTRING(retval);
 }
 
 /*-----------------------------------------------------------------------------
  * array_dims :
- *               returns the dimension of the array pointed to by "v"
+ *               returns the dimensions of the array pointed to by "v", as a "text"
  *----------------------------------------------------------------------------
  */
-char *
-array_dims(ArrayType *v, bool *isNull)
+Datum
+array_dims(PG_FUNCTION_ARGS)
 {
-       char       *p,
-                          *save_p;
+       ArrayType  *v = (ArrayType *) PG_GETARG_VARLENA_P(0);
+       text       *result;
+       char       *p;
        int                     nbytes,
                                i;
        int                *dimv,
                           *lb;
 
-       if (v == (ArrayType *) NULL)
-               RETURN_NULL;
-       nbytes = ARR_NDIM(v) * 33;
-
+       nbytes = ARR_NDIM(v) * 33 + 1;
        /*
         * 33 since we assume 15 digits per number + ':' +'[]'
+        *
+        * +1 allows for temp trailing null
         */
-       save_p = p = (char *) palloc(nbytes + VARHDRSZ);
-       MemSet(save_p, 0, nbytes + VARHDRSZ);
+
+       result = (text *) palloc(nbytes + VARHDRSZ);
+       MemSet(result, 0, nbytes + VARHDRSZ);
+       p = VARDATA(result);
+
        dimv = ARR_DIMS(v);
        lb = ARR_LBOUND(v);
-       p += VARHDRSZ;
+
        for (i = 0; i < ARR_NDIM(v); i++)
        {
                sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
                p += strlen(p);
        }
-       nbytes = strlen(save_p + VARHDRSZ) + VARHDRSZ;
-       memmove(save_p, &nbytes, VARHDRSZ);
-       return save_p;
+       VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ;
+
+       PG_RETURN_TEXT_P(result);
 }
 
 /*---------------------------------------------------------------------------
  * array_ref :
- *       This routing 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
  *       reference otherwise returns the value of the referred element.
  *---------------------------------------------------------------------------
  */
 Datum
 array_ref(ArrayType *array,
-                 int n,
+                 int nSubscripts,
                  int *indx,
-                 int reftype,
+                 bool elmbyval,
                  int elmlen,
                  int arraylen,
                  bool *isNull)
@@ -828,10 +841,11 @@ array_ref(ArrayType *array,
                                offset,
                                nbytes;
        struct varlena *v = NULL;
-       char       *retval = NULL;
+       Datum           result;
+       char       *retval;
 
        if (array == (ArrayType *) NULL)
-               RETURN_NULL;
+               RETURN_NULL(Datum);
        if (arraylen > 0)
        {
 
@@ -841,17 +855,17 @@ array_ref(ArrayType *array,
                if (indx[0] * elmlen > arraylen)
                        elog(ERROR, "array_ref: array bound exceeded");
                retval = (char *) array + indx[0] * elmlen;
-               return _ArrayCast(retval, reftype, elmlen);
+               return _ArrayCast(retval, elmbyval, elmlen);
        }
        dim = ARR_DIMS(array);
        lb = ARR_LBOUND(array);
        ndim = ARR_NDIM(array);
        nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
 
-       if (!SanityCheckInput(ndim, n, dim, lb, indx))
-               RETURN_NULL;
+       if (!SanityCheckInput(ndim, nSubscripts, dim, lb, indx))
+               RETURN_NULL(Datum);
 
-       offset = GetOffset(n, dim, lb, indx);
+       offset = GetOffset(nSubscripts, dim, lb, indx);
 
        if (ARR_IS_LO(array))
        {
@@ -863,33 +877,39 @@ array_ref(ArrayType *array,
                lo_name = (char *) ARR_DATA_PTR(array);
 #ifdef LOARRAY
                if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0)
-                       RETURN_NULL;
+                       RETURN_NULL(Datum);
 #endif
                if (ARR_IS_CHUNKED(array))
                        v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull);
                else
                {
-                       if (lo_lseek(fd, offset, SEEK_SET) < 0)
-                               RETURN_NULL;
+                       if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(fd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
+                               RETURN_NULL(Datum);
 #ifdef LOARRAY
-                       v = (struct varlena *) LOread(fd, elmlen);
+                       v = (struct varlena *)
+                               DatumGetPointer(DirectFunctionCall2(loread,
+                                                                                                       Int32GetDatum(fd),
+                                                                                                       Int32GetDatum(elmlen)));
 #endif
                }
                if (*isNull)
-                       RETURN_NULL;
+                       RETURN_NULL(Datum);
                if (VARSIZE(v) - VARHDRSZ < elmlen)
-                       RETURN_NULL;
-               lo_close(fd);
-               retval = (char *) _ArrayCast((char *) VARDATA(v), reftype, elmlen);
-               if (reftype == 0)
+                       RETURN_NULL(Datum);
+               DirectFunctionCall1(lo_close, Int32GetDatum(fd));
+               result = _ArrayCast((char *) VARDATA(v), elmbyval, elmlen);
+               if (! elmbyval)
                {                                               /* not by value */
                        char       *tempdata = palloc(elmlen);
 
-                       memmove(tempdata, retval, elmlen);
-                       retval = tempdata;
+                       memmove(tempdata, DatumGetPointer(result), elmlen);
+                       result = PointerGetDatum(tempdata);
                }
                pfree(v);
-               return (Datum) retval;
+               return result;
        }
 
        if (elmlen > 0)
@@ -897,32 +917,25 @@ array_ref(ArrayType *array,
                offset = offset * elmlen;
                /* off the end of the array */
                if (nbytes - offset < 1)
-                       RETURN_NULL;
+                       RETURN_NULL(Datum);
                retval = ARR_DATA_PTR(array) + offset;
-               return _ArrayCast(retval, reftype, elmlen);
+               return _ArrayCast(retval, elmbyval, elmlen);
        }
        else
        {
-               bool            done = false;
-               char       *temp;
                int                     bytes = nbytes;
 
-               temp = ARR_DATA_PTR(array);
+               retval = ARR_DATA_PTR(array);
                i = 0;
-               while (bytes > 0 && !done)
+               while (bytes > 0)
                {
                        if (i == offset)
-                       {
-                               retval = temp;
-                               done = true;
-                       }
-                       bytes -= INTALIGN(*(int32 *) temp);
-                       temp += INTALIGN(*(int32 *) temp);
+                               return PointerGetDatum(retval);
+                       bytes -= INTALIGN(*(int32 *) retval);
+                       retval += INTALIGN(*(int32 *) retval);
                        i++;
                }
-               if (!done)
-                       RETURN_NULL;
-               return (Datum) retval;
+               RETURN_NULL(Datum);
        }
 }
 
@@ -933,13 +946,13 @@ array_ref(ArrayType *array,
  *                and returns a pointer to it.
  *-----------------------------------------------------------------------------
  */
-Datum
+ArrayType *
 array_clip(ArrayType *array,
-                  int n,
+                  int nSubscripts,
                   int *upperIndx,
                   int *lowerIndx,
-                  int reftype,
-                  int len,
+                  bool elmbyval,
+                  int elmlen,
                   bool *isNull)
 {
        int                     i,
@@ -953,22 +966,20 @@ array_clip(ArrayType *array,
 
        /* timer_start(); */
        if (array == (ArrayType *) NULL)
-               RETURN_NULL;
+               RETURN_NULL(ArrayType *);
        dim = ARR_DIMS(array);
        lb = ARR_LBOUND(array);
        ndim = ARR_NDIM(array);
        nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
 
-       if (!SanityCheckInput(ndim, n, dim, lb, upperIndx))
-               RETURN_NULL;
+       if (!SanityCheckInput(ndim, nSubscripts, dim, lb, upperIndx) ||
+               !SanityCheckInput(ndim, nSubscripts, dim, lb, lowerIndx))
+               RETURN_NULL(ArrayType *);
 
-       if (!SanityCheckInput(ndim, n, dim, lb, lowerIndx))
-               RETURN_NULL;
-
-       for (i = 0; i < n; i++)
+       for (i = 0; i < nSubscripts; i++)
                if (lowerIndx[i] > upperIndx[i])
                        elog(ERROR, "lowerIndex cannot be larger than upperIndx");
-       mda_get_range(n, span, lowerIndx, upperIndx);
+       mda_get_range(nSubscripts, span, lowerIndx, upperIndx);
 
        if (ARR_IS_LO(array))
        {
@@ -982,23 +993,23 @@ array_clip(ArrayType *array,
                                        isDestLO = true,
                                        rsize;
 
-               if (len < 0)
-                       elog(ERROR, "array_clip: array of variable length objects not supported");
+               if (elmlen < 0)
+                       elog(ERROR, "array_clip: array of variable length objects not implemented");
 #ifdef LOARRAY
                lo_name = (char *) ARR_DATA_PTR(array);
                if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0)
-                       RETURN_NULL;
+                       RETURN_NULL(ArrayType *);
                newname = _array_newLO(&newfd, Unix);
 #endif
-               bytes = strlen(newname) + 1 + ARR_OVERHEAD(n);
+               bytes = strlen(newname) + 1 + ARR_OVERHEAD(nSubscripts);
                newArr = (ArrayType *) palloc(bytes);
                memmove(newArr, array, sizeof(ArrayType));
                memmove(newArr, &bytes, sizeof(int));
-               memmove(ARR_DIMS(newArr), span, n * sizeof(int));
-               memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int));
+               memmove(ARR_DIMS(newArr), span, nSubscripts * sizeof(int));
+               memmove(ARR_LBOUND(newArr), lowerIndx, nSubscripts * sizeof(int));
                strcpy(ARR_DATA_PTR(newArr), newname);
 
-               rsize = compute_size(lowerIndx, upperIndx, nlen);
+               rsize = compute_size(lowerIndx, upperIndx, nSubscripts, elmlen);
                if (rsize < MAX_BUFF_SIZE)
                {
                        char       *buff;
@@ -1009,19 +1020,21 @@ array_clip(ArrayType *array,
                                isDestLO = false;
                        if (ARR_IS_CHUNKED(array))
                        {
-                               _ReadChunkArray(lowerIndx, upperIndx, len, fd, &(buff[VARHDRSZ]),
+                               _ReadChunkArray(lowerIndx, upperIndx, elmlen, fd, &(buff[VARHDRSZ]),
                                                                array, 0, isNull);
                        }
                        else
                        {
-                               _ReadArray(lowerIndx, upperIndx, len, fd, (int) &(buff[VARHDRSZ]),
+                               _ReadArray(lowerIndx, upperIndx, elmlen, fd, (int) &(buff[VARHDRSZ]),
                                                   array,
                                                   0, isNull);
                        }
                        memmove(buff, &rsize, VARHDRSZ);
 #ifdef LOARRAY
                        if (!*isNull)
-                               bytes = LOwrite(newfd, (struct varlena *) buff);
+                               bytes = DatumGetInt32(DirectFunctionCall2(lowrite,
+                                                                         Int32GetDatum(newfd),
+                                                                         PointerGetDatum(buff)));
 #endif
                        pfree(buff);
                }
@@ -1029,11 +1042,11 @@ array_clip(ArrayType *array,
                {
                        if (ARR_IS_CHUNKED(array))
                        {
-                               _ReadChunkArray(lowerIndx, upperIndx, len, fd, (char *) newfd, array,
+                               _ReadChunkArray(lowerIndx, upperIndx, elmlen, fd, (char *) newfd, array,
                                                                1, isNull);
                        }
                        else
-                               _ReadArray(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull);
+                               _ReadArray(lowerIndx, upperIndx, elmlen, fd, newfd, array, 1, isNull);
                }
 #ifdef LOARRAY
                LOclose(fd);
@@ -1045,42 +1058,42 @@ array_clip(ArrayType *array,
                        newArr = NULL;
                }
                /* timer_end(); */
-               return (Datum) newArr;
+               return newArr;
        }
 
-       if (len > 0)
+       if (elmlen > 0)
        {
-               bytes = getNitems(n, span);
-               bytes = bytes * len + ARR_OVERHEAD(n);
+               bytes = getNitems(nSubscripts, span);
+               bytes = bytes * elmlen + ARR_OVERHEAD(nSubscripts);
        }
        else
        {
                bytes = _ArrayClipCount(lowerIndx, upperIndx, array);
-               bytes += ARR_OVERHEAD(n);
+               bytes += ARR_OVERHEAD(nSubscripts);
        }
        newArr = (ArrayType *) palloc(bytes);
        memmove(newArr, array, sizeof(ArrayType));
        memmove(newArr, &bytes, sizeof(int));
-       memmove(ARR_DIMS(newArr), span, n * sizeof(int));
-       memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int));
-       _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 1);
-       return (Datum) newArr;
+       memmove(ARR_DIMS(newArr), span, nSubscripts * sizeof(int));
+       memmove(ARR_LBOUND(newArr), lowerIndx, nSubscripts * sizeof(int));
+       _ArrayRange(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(newArr), array, 1);
+       return newArr;
 }
 
 /*-----------------------------------------------------------------------------
  * array_set  :
- *               This routine sets the value of an array location (specified by an index array)
- *               to a new value specified by "dataPtr".
+ *               This routine sets the value of an array location (specified by
+ *               an index array) to a new value specified by "dataValue".
  * result :
  *               returns a pointer to the modified array.
  *-----------------------------------------------------------------------------
  */
-char *
+ArrayType *
 array_set(ArrayType *array,
-                 int n,
+                 int nSubscripts,
                  int *indx,
-                 char *dataPtr,
-                 int reftype,
+                 Datum dataValue,
+                 bool elmbyval,
                  int elmlen,
                  int arraylen,
                  bool *isNull)
@@ -1093,7 +1106,7 @@ array_set(ArrayType *array,
        char       *pos;
 
        if (array == (ArrayType *) NULL)
-               RETURN_NULL;
+               RETURN_NULL(ArrayType *);
        if (arraylen > 0)
        {
 
@@ -1103,20 +1116,20 @@ array_set(ArrayType *array,
                if (indx[0] * elmlen > arraylen)
                        elog(ERROR, "array_ref: array bound exceeded");
                pos = (char *) array + indx[0] * elmlen;
-               ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
-               return (char *) array;
+               ArrayCastAndSet(dataValue, elmbyval, elmlen, pos);
+               return array;
        }
        dim = ARR_DIMS(array);
        lb = ARR_LBOUND(array);
        ndim = ARR_NDIM(array);
        nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
 
-       if (!SanityCheckInput(ndim, n, dim, lb, indx))
+       if (!SanityCheckInput(ndim, nSubscripts, dim, lb, indx))
        {
                elog(ERROR, "array_set: array bound exceeded");
-               return (char *) array;
+               return array;
        }
-       offset = GetOffset(n, dim, lb, indx);
+       offset = GetOffset(nSubscripts, dim, lb, indx);
 
        if (ARR_IS_LO(array))
        {
@@ -1130,30 +1143,33 @@ array_set(ArrayType *array,
 
                lo_name = ARR_DATA_PTR(array);
                if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
-                       return (char *) array;
+                       return array;
 #endif
-               if (lo_lseek(fd, offset, SEEK_SET) < 0)
-                       return (char *) array;
+               if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(fd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
+                       return array;
                v = (struct varlena *) palloc(elmlen + VARHDRSZ);
                VARSIZE(v) = elmlen + VARHDRSZ;
-               ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, VARDATA(v));
+               ArrayCastAndSet(dataValue, elmbyval, elmlen, VARDATA(v));
 #ifdef LOARRAY
-               n = LOwrite(fd, v);
+               if (DatumGetInt32(DirectFunctionCall2(lowrite,
+                                                                                         Int32GetDatum(fd),
+                                                                                         PointerGetDatum(v)))
+                       != elmlen)
+                       RETURN_NULL(ArrayType *);
 #endif
-
-               /*
-                * if (n < VARSIZE(v) - VARHDRSZ) RETURN_NULL;
-                */
                pfree(v);
-               lo_close(fd);
-               return (char *) array;
+               DirectFunctionCall1(lo_close, Int32GetDatum(fd));
+               return array;
        }
        if (elmlen > 0)
        {
                offset = offset * elmlen;
                /* off the end of the array */
                if (nbytes - offset < 1)
-                       return (char *) array;
+                       return array;
                pos = ARR_DATA_PTR(array) + offset;
        }
        else
@@ -1170,18 +1186,18 @@ array_set(ArrayType *array,
 
                elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset);
                oldlen = INTALIGN(*(int32 *) elt_ptr);
-               newlen = INTALIGN(*(int32 *) dataPtr);
+               newlen = INTALIGN(*(int32 *) DatumGetPointer(dataValue));
 
                if (oldlen == newlen)
                {
                        /* new element with same size, overwrite old data */
-                       ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, elt_ptr);
-                       return (char *) array;
+                       ArrayCastAndSet(dataValue, elmbyval, elmlen, elt_ptr);
+                       return array;
                }
 
                /* new element with different size, reallocate the array */
                oldsize = array->size;
-               lth0 = ARR_OVERHEAD(n);
+               lth0 = ARR_OVERHEAD(nSubscripts);
                lth1 = (int) (elt_ptr - ARR_DATA_PTR(array));
                lth2 = (int) (oldsize - lth0 - lth1 - oldlen);
                newsize = lth0 + lth1 + newlen + lth2;
@@ -1189,16 +1205,16 @@ array_set(ArrayType *array,
                newarray = (ArrayType *) palloc(newsize);
                memmove((char *) newarray, (char *) array, lth0 + lth1);
                newarray->size = newsize;
-               newlen = ArrayCastAndSet(dataPtr, (bool) reftype, elmlen,
+               newlen = ArrayCastAndSet(dataValue, elmbyval, elmlen,
                                                                 (char *) newarray + lth0 + lth1);
                memmove((char *) newarray + lth0 + lth1 + newlen,
                                (char *) array + lth0 + lth1 + oldlen, lth2);
 
                /* ??? who should free this storage ??? */
-               return (char *) newarray;
+               return newarray;
        }
-       ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
-       return (char *) array;
+       ArrayCastAndSet(dataValue, elmbyval, elmlen, pos);
+       return array;
 }
 
 /*----------------------------------------------------------------------------
@@ -1210,14 +1226,14 @@ array_set(ArrayType *array,
  *               returns a pointer to the modified array.
  *----------------------------------------------------------------------------
  */
-char *
+ArrayType *
 array_assgn(ArrayType *array,
-                       int n,
+                       int nSubscripts,
                        int *upperIndx,
                        int *lowerIndx,
                        ArrayType *newArr,
-                       int reftype,
-                       int len,
+                       bool elmbyval,
+                       int elmlen,
                        bool *isNull)
 {
        int                     i,
@@ -1226,19 +1242,19 @@ array_assgn(ArrayType *array,
                           *lb;
 
        if (array == (ArrayType *) NULL)
-               RETURN_NULL;
-       if (len < 0)
-               elog(ERROR, "array_assgn:updates on arrays of variable length elements not allowed");
+               RETURN_NULL(ArrayType *);
+       if (elmlen < 0)
+               elog(ERROR, "array_assgn: updates on arrays of variable length elements not implemented");
 
        dim = ARR_DIMS(array);
        lb = ARR_LBOUND(array);
        ndim = ARR_NDIM(array);
 
-       if (!SanityCheckInput(ndim, n, dim, lb, upperIndx) ||
-               !SanityCheckInput(ndim, n, dim, lb, lowerIndx))
-               return (char *) array;
+       if (!SanityCheckInput(ndim, nSubscripts, dim, lb, upperIndx) ||
+               !SanityCheckInput(ndim, nSubscripts, dim, lb, lowerIndx))
+               RETURN_NULL(ArrayType *);
 
-       for (i = 0; i < n; i++)
+       for (i = 0; i < nSubscripts; i++)
                if (lowerIndx[i] > upperIndx[i])
                        elog(ERROR, "lowerIndex larger than upperIndx");
 
@@ -1252,46 +1268,60 @@ array_assgn(ArrayType *array,
 
                lo_name = (char *) ARR_DATA_PTR(array);
                if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
-                       return (char *) array;
+                       return array;
 #endif
                if (ARR_IS_LO(newArr))
                {
 #ifdef LOARRAY
                        lo_name = (char *) ARR_DATA_PTR(newArr);
                        if ((newfd = LOopen(lo_name, ARR_IS_INV(newArr) ? INV_READ : O_RDONLY)) < 0)
-                               return (char *) array;
+                               return array;
 #endif
-                       _LOArrayRange(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull);
-                       lo_close(newfd);
+                       _LOArrayRange(lowerIndx, upperIndx, elmlen, fd, newfd, array, 1, isNull);
+                       DirectFunctionCall1(lo_close, Int32GetDatum(newfd));
                }
                else
                {
-                       _LOArrayRange(lowerIndx, upperIndx, len, fd, (int) ARR_DATA_PTR(newArr),
+                       _LOArrayRange(lowerIndx, upperIndx, elmlen, fd, (int) ARR_DATA_PTR(newArr),
                                                  array, 0, isNull);
                }
-               lo_close(fd);
-               return (char *) array;
+               DirectFunctionCall1(lo_close, Int32GetDatum(fd));
+               return array;
        }
-       _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 0);
-       return (char *) array;
+       _ArrayRange(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(newArr), array, 0);
+       return array;
 }
 
 /*
  * array_map()
  *
- * Map an arbitrary function to an array and return a new array with
- * same dimensions and the source elements transformed by fn().
+ * Map an array through an arbitrary function.  Return a new array with
+ * same dimensions and each source element transformed by fn().  Each
+ * source element is passed as the first argument to fn(); additional
+ * arguments to be passed to fn() can be specified by the caller.
+ * The output array can have a different element type than the input.
+ *
+ * Parameters are:
+ * * fcinfo: a function-call data structure pre-constructed by the caller
+ *   to be ready to call the desired function, with everything except the
+ *   first argument position filled in.  In particular, flinfo identifies
+ *   the function fn(), and if nargs > 1 then argument positions after the
+ *   first must be preset to the additional values to be passed.  The
+ *   first argument position initially holds the input array value.
+ * * inpType: OID of element type of input array.  This must be the same as,
+ *   or binary-compatible with, the first argument type of fn().
+ * * retType: OID of element type of output array.  This must be the same as,
+ *   or binary-compatible with, the result type of fn().
+ *
+ * NB: caller must assure that input array is not NULL.  Currently,
+ * any additional parameters passed to fn() may not be specified as NULL
+ * either.
  */
-ArrayType  *
-array_map(ArrayType *v,
-                 Oid type,
-                 char *(*fn) (),
-                 Oid retType,
-                 int nargs,
-                 ...)
+Datum
+array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
 {
+       ArrayType  *v;
        ArrayType  *result;
-       void       *args[4];
        char      **values;
        char       *elt;
        int                *dim;
@@ -1309,35 +1339,31 @@ array_map(ArrayType *v,
        char            typalign;
        char       *s;
        char       *p;
-       va_list         ap;
+
+       /* Get input array */
+       if (fcinfo->nargs < 1)
+               elog(ERROR, "array_map: invalid nargs: %d", fcinfo->nargs);
+       if (PG_ARGISNULL(0))
+               elog(ERROR, "array_map: null input array");
+       v = (ArrayType *) PG_GETARG_VARLENA_P(0);
 
        /* Large objects not yet supported */
        if (ARR_IS_LO(v) == true)
                elog(ERROR, "array_map: large objects not supported");
 
-       /* Check nargs */
-       if ((nargs < 0) || (nargs > 4))
-               elog(ERROR, "array_map: invalid nargs: %d", nargs);
-
-       /* Copy extra args to local variable */
-       va_start(ap, nargs);
-       for (i = 0; i < nargs; i++)
-               args[i] = (void *) va_arg(ap, char *);
-       va_end(ap);
-
-       /* Lookup source and result types. Unneeded variables are reused. */
-       system_cache_lookup(type, false, &inp_typlen, &inp_typbyval,
-                                               &typdelim, &typelem, &proc, &typalign);
-       system_cache_lookup(retType, false, &typlen, &typbyval,
-                                               &typdelim, &typelem, &proc, &typalign);
-
        ndim = ARR_NDIM(v);
        dim = ARR_DIMS(v);
        nitems = getNitems(ndim, dim);
 
        /* Check for empty array */
        if (nitems <= 0)
-               return v;
+               PG_RETURN_POINTER(v);
+
+       /* Lookup source and result types. Unneeded variables are reused. */
+       system_cache_lookup(inpType, false, &inp_typlen, &inp_typbyval,
+                                               &typdelim, &typelem, &proc, &typalign);
+       system_cache_lookup(retType, false, &typlen, &typbyval,
+                                               &typdelim, &typelem, &proc, &typalign);
 
        /* Allocate temporary array for new values */
        values = (char **) palloc(nitems * sizeof(char *));
@@ -1376,33 +1402,23 @@ array_map(ArrayType *v,
                }
 
                /*
-                * Apply the given function to source elt and extra args. nargs is
-                * the number of extra args taken by fn().
+                * Apply the given function to source elt and extra args.
+                *
+                * We assume the extra args are non-NULL, so need not check
+                * whether fn() is strict.  Would need to do more work here
+                * to support arrays containing nulls, too.
                 */
-               switch (nargs)
-               {
-                       case 0:
-                               p = (char *) (*fn) (elt);
-                               break;
-                       case 1:
-                               p = (char *) (*fn) (elt, args[0]);
-                               break;
-                       case 2:
-                               p = (char *) (*fn) (elt, args[0], args[1]);
-                               break;
-                       case 3:
-                               p = (char *) (*fn) (elt, args[0], args[1], args[2]);
-                               break;
-                       case 4:
-                       default:
-                               p = (char *) (*fn) (elt, args[0], args[1], args[2], args[3]);
-                               break;
-               }
+               fcinfo->arg[0] = (Datum) elt;
+               fcinfo->argnull[0] = false;
+               fcinfo->isnull = false;
+               p = (char *) FunctionCallInvoke(fcinfo);
+               if (fcinfo->isnull)
+                       elog(ERROR, "array_map: cannot handle NULL in array");
 
                /* Update values and total result size */
                if (typbyval)
                {
-                       values[i] = (char *) p;
+                       values[i] = p;
                        nbytes += typlen;
                }
                else
@@ -1416,7 +1432,7 @@ array_map(ArrayType *v,
                                p = (char *) palloc(len);
                                memcpy(p, elt, len);
                        }
-                       values[i] = (char *) p;
+                       values[i] = p;
                        nbytes += len;
                }
        }
@@ -1435,26 +1451,27 @@ array_map(ArrayType *v,
                                  ARR_DATA_PTR(result), nitems,
                                  typlen, typalign, typbyval);
 
-       return result;
+       PG_RETURN_POINTER(result);
 }
 
 /*-----------------------------------------------------------------------------
  * array_eq :
  *               compares two arrays for equality
  * result :
- *               returns 1 if the arrays are equal, 0 otherwise.
+ *               returns true if the arrays are equal, false otherwise.
  *-----------------------------------------------------------------------------
  */
-int
-array_eq(ArrayType *array1, ArrayType *array2)
+Datum
+array_eq(PG_FUNCTION_ARGS)
 {
-       if ((array1 == NULL) || (array2 == NULL))
-               return 0;
-       if (*(int *) array1 != *(int *) array2)
-               return 0;
-       if (memcmp(array1, array2, *(int *) array1))
-               return 0;
-       return 1;
+       ArrayType  *array1 = (ArrayType *) PG_GETARG_VARLENA_P(0);
+       ArrayType  *array2 = (ArrayType *) PG_GETARG_VARLENA_P(1);
+
+       if (*(int32 *) array1 != *(int32 *) array2)
+               PG_RETURN_BOOL(false);
+       if (memcmp(array1, array2, *(int32 *) array1) != 0)
+               PG_RETURN_BOOL(false);
+       PG_RETURN_BOOL(true);
 }
 
 /***************************************************************************/
@@ -1473,7 +1490,7 @@ system_cache_lookup(Oid element_type,
        HeapTuple       typeTuple;
        Form_pg_type typeStruct;
 
-       typeTuple = SearchSysCacheTuple(TYPOID,
+       typeTuple = SearchSysCacheTuple(TYPEOID,
                                                                        ObjectIdGetDatum(element_type),
                                                                        0, 0, 0);
 
@@ -1521,7 +1538,7 @@ _ArrayCast(char *value, bool byval, int len)
 
 
 static int
-ArrayCastAndSet(char *src,
+ArrayCastAndSet(Datum src,
                                bool typbyval,
                                int typlen,
                                char *dest)
@@ -1541,18 +1558,18 @@ ArrayCastAndSet(char *src,
                                        *(int16 *) dest = DatumGetInt16(src);
                                        break;
                                case 4:
-                                       *(int32 *) dest = (int32) src;
+                                       *(int32 *) dest = DatumGetInt32(src);
                                        break;
                        }
                }
                else
-                       memmove(dest, src, typlen);
+                       memmove(dest, DatumGetPointer(src), typlen);
                inc = typlen;
        }
        else
        {
-               memmove(dest, src, *(int32 *) src);
-               inc = (INTALIGN(*(int32 *) src));
+               memmove(dest, DatumGetPointer(src), *(int32 *) DatumGetPointer(src));
+               inc = (INTALIGN(*(int32 *) DatumGetPointer(src)));
        }
        return inc;
 }
@@ -1750,7 +1767,10 @@ _LOArrayRange(int *st,
        mda_get_prod(n, dim, prod);
        st_pos = tuple2linear(n, st, prod);
        offset = st_pos * bsize;
-       if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
+       if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(srcfd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
                return;
        mda_get_range(n, span, st, endp);
        mda_get_offset_values(n, dist, prod, span);
@@ -1762,7 +1782,10 @@ _LOArrayRange(int *st,
        do
        {
                offset += (dist[j] * bsize);
-               if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
+               if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(srcfd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
                        return;
                tmp = _LOtransfer((char **) &srcfd, inc, 1, (char **) &destfd, isSrcLO, 1);
                if (tmp < inc)
@@ -1804,7 +1827,10 @@ _ReadArray(int *st,
        mda_get_prod(n, dim, prod);
        st_pos = tuple2linear(n, st, prod);
        offset = st_pos * bsize;
-       if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
+       if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(srcfd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
                return;
        mda_get_range(n, span, st, endp);
        mda_get_offset_values(n, dist, prod, span);
@@ -1816,7 +1842,10 @@ _ReadArray(int *st,
        do
        {
                offset += (dist[j] * bsize);
-               if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
+               if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
+                                                         Int32GetDatum(srcfd),
+                                                         Int32GetDatum(offset),
+                                                         Int32GetDatum(SEEK_SET))) < 0)
                        return;
                tmp = _LOtransfer((char **) &destfd, inc, 1, (char **) &srcfd, 1, isDestLO);
                if (tmp < inc)
@@ -1835,7 +1864,9 @@ _LOtransfer(char **destfd,
                        int isDestLO)
 {
 #define MAX_READ (512 * 1024)
+#if !defined(min)
 #define min(a, b) (a < b ? a : b)
+#endif
        struct varlena *v = NULL;
        int                     tmp,
                                inc,
@@ -1847,13 +1878,18 @@ _LOtransfer(char **destfd,
                         resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc)
                {
 #ifdef LOARRAY
-                       v = (struct varlena *) LOread((int) *srcfd, inc);
+                       v = (struct varlena *)
+                               DatumGetPointer(DirectFunctionCall2(loread,
+                                                               Int32GetDatum((int32) *srcfd),
+                                                               Int32GetDatum(inc)));
                        if (VARSIZE(v) - VARHDRSZ < inc)
                        {
                                pfree(v);
                                return -1;
                        }
-                       tmp += LOwrite((int) *destfd, v);
+                       tmp += DatumGetInt32(DirectFunctionCall2(lowrite,
+                                                                Int32GetDatum((int32) *destfd),
+                                                                PointerGetDatum(v)));
 #endif
                        pfree(v);