/*-------------------------------------------------------------------------
*
- * arrayfuncs.c--
+ * 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.35 1999/01/17 06:18:45 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 "postgres.h"
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
-
-#include "utils/syscache.h"
-#include "utils/memutils.h"
-#include "storage/fd.h"
#include "fmgr.h"
-#include "utils/array.h"
-
-#include "libpq/libpq-fs.h"
#include "libpq/be-fsstubs.h"
+#include "libpq/libpq-fs.h"
+#include "storage/fd.h"
+#include "utils/array.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
#define ASSGN "="
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);
/*---------------------------------------------------------------------
* 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;
nitems;
int32 nbytes;
char *dataPtr;
- ArrayType *retval = NULL;
+ ArrayType *retval;
int ndim,
dim[MAXDIM],
lBound[MAXDIM];
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 == '{')
{
/* array not a large object */
- dataPtr =
- (char *) _ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
+ dataPtr = (char *) _ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
typmod, typdelim, typlen, typbyval, typalign,
- &nbytes);
+ &nbytes);
nbytes += ARR_OVERHEAD(ndim);
retval = (ArrayType *) palloc(nbytes);
MemSet(retval, 0, nbytes);
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);
}
/*-----------------------------------------------------------------------------
- * _ArrayCount --
+ * _ArrayCount
* Counts the number of dimensions and the *dim array for an array string.
* The syntax for array input is C-like nested curly braces
*-----------------------------------------------------------------------------
*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)
if (values[i])
{
if (typalign == 'd')
- *nbytes += DOUBLEALIGN(*(int32 *) values[i]);
+ *nbytes += MAXALIGN(*(int32 *) values[i]);
else
*nbytes += INTALIGN(*(int32 *) values[i]);
}
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;
{
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,
{
int inc;
- inc = ArrayCastAndSet(values[i], typbyval, typlen, p);
+ inc = ArrayCastAndSet((Datum) values[i], typbyval, typlen, p);
p += inc;
if (!typbyval)
pfree(values[i]);
* 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;
typelem;
FmgrInfo outputproc;
char typalign;
-
char *p,
*tmp,
*retval,
i,
j,
k,
+#ifndef TCL_ARRAYS
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,
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);
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
for (tmp = values[i]; *tmp; tmp++)
{
overall_length += 1;
+#ifndef TCL_ARRAYS
if (*tmp == '"')
overall_length += 1;
+#endif
}
overall_length += 1;
}
if (!typbyval)
{
strcat(p, "\"");
+#ifndef TCL_ARRAYS
l = strlen(p);
for (tmp = values[k]; *tmp; tmp++)
{
p[l++] = *tmp;
}
p[l] = '\0';
+#else
+ strcat(p, values[k]);
+#endif
strcat(p, "\"");
}
else
} 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)
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)
{
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))
{
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)
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);
}
}
* 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,
/* 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))
{
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, n, len);
+ rsize = compute_size(lowerIndx, upperIndx, nSubscripts, elmlen);
if (rsize < MAX_BUFF_SIZE)
{
char *buff;
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);
}
{
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);
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)
char *pos;
if (array == (ArrayType *) NULL)
- RETURN_NULL;
+ RETURN_NULL(ArrayType *);
if (arraylen > 0)
{
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))
{
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
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;
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;
}
/*----------------------------------------------------------------------------
* 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,
*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");
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 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.
+ */
+Datum
+array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
+{
+ ArrayType *v;
+ ArrayType *result;
+ char **values;
+ char *elt;
+ int *dim;
+ int ndim;
+ int nitems;
+ int i;
+ int nbytes = 0;
+ int inp_typlen;
+ bool inp_typbyval;
+ int typlen;
+ bool typbyval;
+ char typdelim;
+ Oid typelem;
+ Oid proc;
+ char typalign;
+ char *s;
+ char *p;
+
+ /* 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");
+
+ ndim = ARR_NDIM(v);
+ dim = ARR_DIMS(v);
+ nitems = getNitems(ndim, dim);
+
+ /* Check for empty array */
+ if (nitems <= 0)
+ 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 *));
+ MemSet(values, 0, nitems * sizeof(char *));
+
+ /* Loop over source data */
+ s = (char *) ARR_DATA_PTR(v);
+ for (i = 0; i < nitems; i++)
+ {
+ /* Get source element */
+ if (inp_typbyval)
+ {
+ switch (inp_typlen)
+ {
+ case 1:
+ elt = (char *) ((int) (*(char *) s));
+ break;
+ case 2:
+ elt = (char *) ((int) (*(int16 *) s));
+ break;
+ case 3:
+ case 4:
+ default:
+ elt = (char *) (*(int32 *) s);
+ break;
+ }
+ s += inp_typlen;
+ }
+ else
+ {
+ elt = s;
+ if (inp_typlen > 0)
+ s += inp_typlen;
+ else
+ s += INTALIGN(*(int32 *) s);
+ }
+
+ /*
+ * 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.
+ */
+ 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] = p;
+ nbytes += typlen;
+ }
+ else
+ {
+ int len;
+
+ 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 */
+ nbytes += ARR_OVERHEAD(ndim);
+ result = (ArrayType *) palloc(nbytes);
+ MemSet(result, 0, nbytes);
+
+ memcpy((char *) result, (char *) &nbytes, sizeof(int));
+ memcpy((char *) ARR_NDIM_PTR(result), (char *) &ndim, sizeof(int));
+ memcpy((char *) ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int));
+
+ /* Copy new values into the result array. values is pfreed. */
+ _CopyArrayEls((char **) values,
+ ARR_DATA_PTR(result), nitems,
+ typlen, typalign, typbyval);
+
+ 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);
}
/***************************************************************************/
HeapTuple typeTuple;
Form_pg_type typeStruct;
- typeTuple = SearchSysCacheTuple(TYPOID,
+ typeTuple = SearchSysCacheTuple(TYPEOID,
ObjectIdGetDatum(element_type),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
{
- elog(ERROR, "array_out: Cache lookup failed for type %d\n",
+ elog(ERROR, "array_out: Cache lookup failed for type %u\n",
element_type);
return;
}
static int
-ArrayCastAndSet(char *src,
+ArrayCastAndSet(Datum src,
bool typbyval,
int typlen,
char *dest)
*(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;
}
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);
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)
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);
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)
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,
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);
char saveName[NAME_LEN];
p = (char *) palloc(NAME_LEN);
- sprintf(p, "/Arry.%d", newoid());
+ sprintf(p, "/Arry.%u", newoid());
strcpy(saveName, p);
#ifdef LOARRAY
if ((*fd = LOcreat(saveName, 0600, flag)) < 0)