aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-07-22 03:34:43 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-07-22 03:34:43 +0000
commitd0e17e211230d37f26843711115864a87d0eae18 (patch)
treeb039e4879d7faeb1ddfc33f6051af4b21fbc3ce4 /src
parentec37ea1cc1356f1a0b7dad1d9e4933e50bea583f (diff)
downloadpostgresql-d0e17e211230d37f26843711115864a87d0eae18.tar.gz
postgresql-d0e17e211230d37f26843711115864a87d0eae18.zip
Arrays are toastable. (At least if you initdb, which I didn't force.)
Remove a bunch of crufty code for large-object-based arrays, which is superseded by TOAST and likely hasn't worked in a long time anyway. Clean up array code a little, and in particular eliminate its habit of scribbling on the input array (ie, modifying the input tuple :-().
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/define.c8
-rw-r--r--src/backend/executor/execQual.c69
-rw-r--r--src/backend/utils/adt/Makefile4
-rw-r--r--src/backend/utils/adt/arrayfuncs.c1061
-rw-r--r--src/backend/utils/adt/arrayutils.c106
-rw-r--r--src/backend/utils/adt/chunk.c712
-rw-r--r--src/include/catalog/pg_type.h98
-rw-r--r--src/include/utils/array.h122
8 files changed, 457 insertions, 1723 deletions
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index b90ef61a3b0..cf31e5edb1f 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.45 2000/07/17 03:04:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.46 2000/07/22 03:34:26 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -691,10 +691,10 @@ DefineType(char *typeName, List *parameters)
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
- defaultValue, /* default type value */
+ NULL, /* never a default type value */
false, /* never passed by value */
- alignment,
- 'p'); /* ARRAY doesn't support TOAST yet */
+ alignment, /* NB: must be 'i' or 'd' for arrays... */
+ 'x'); /* ARRAY is always toastable */
pfree(shadow_type);
}
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 48cd8aa169c..1aeb07a7a9f 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.74 2000/07/17 03:04:51 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.75 2000/07/22 03:34:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,9 +67,15 @@ static Datum ExecMakeFunctionResult(Node *node, List *arguments,
/*
* ExecEvalArrayRef
*
- * This function takes an ArrayRef and returns a Const Node if it
- * is an array reference or returns the changed Array Node if it is
- * an array assignment.
+ * This function takes an ArrayRef and returns the extracted Datum
+ * if it's a simple reference, or the modified array value if it's
+ * an array assignment (read array element insertion).
+ *
+ * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
+ * even though that might seem natural, because this code needs to support
+ * both varlena arrays and fixed-length array types. DatumGetArrayTypeP()
+ * only works for the varlena kind. The routines we call in arrayfuncs.c
+ * have to know the difference (that's what they need refattrlength for).
*/
static Datum
ExecEvalArrayRef(ArrayRef *arrayRef,
@@ -77,7 +83,8 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
bool *isNull,
bool *isDone)
{
- ArrayType *array_scanner;
+ ArrayType *array_source;
+ ArrayType *resultArray;
List *elt;
int i = 0,
j = 0;
@@ -90,7 +97,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (arrayRef->refexpr != NULL)
{
- array_scanner = (ArrayType *)
+ array_source = (ArrayType *)
DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
econtext,
isNull,
@@ -110,7 +117,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
* the INSERT column list. This is a kluge, but it's not real
* clear what the semantics ought to be...
*/
- array_scanner = NULL;
+ array_source = NULL;
}
foreach(elt, arrayRef->refupperindexpr)
@@ -162,43 +169,45 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (*isNull)
return (Datum) NULL;
- if (array_scanner == NULL)
+ if (array_source == NULL)
return sourceData; /* XXX do something else? */
- /*
- * XXX shouldn't we copy the array value before modifying it??
- *
- * Or perhaps these array routines should deliver a modified copy
- * instead of changing the source in-place.
- */
if (lIndex == NULL)
- return PointerGetDatum(array_set(array_scanner, i,
- upper.indx,
- sourceData,
- arrayRef->refelembyval,
- arrayRef->refelemlength,
- arrayRef->refattrlength,
- isNull));
- return PointerGetDatum(array_assgn(array_scanner, i,
- upper.indx, lower.indx,
- (ArrayType *) DatumGetPointer(sourceData),
- arrayRef->refelembyval,
- arrayRef->refelemlength,
- isNull));
+ resultArray = array_set(array_source, i,
+ upper.indx,
+ sourceData,
+ arrayRef->refelembyval,
+ arrayRef->refelemlength,
+ arrayRef->refattrlength,
+ isNull);
+ else
+ resultArray = array_set_slice(array_source, i,
+ upper.indx, lower.indx,
+ (ArrayType *) DatumGetPointer(sourceData),
+ arrayRef->refelembyval,
+ arrayRef->refelemlength,
+ arrayRef->refattrlength,
+ isNull);
+ return PointerGetDatum(resultArray);
}
if (lIndex == NULL)
- return array_ref(array_scanner, i,
+ return array_ref(array_source, i,
upper.indx,
arrayRef->refelembyval,
arrayRef->refelemlength,
arrayRef->refattrlength,
isNull);
- return PointerGetDatum(array_clip(array_scanner, i,
+ else
+ {
+ resultArray = array_get_slice(array_source, i,
upper.indx, lower.indx,
arrayRef->refelembyval,
arrayRef->refelemlength,
- isNull));
+ arrayRef->refattrlength,
+ isNull);
+ return PointerGetDatum(resultArray);
+ }
}
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index ba39ab03003..0f42d93aadb 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for utils/adt
#
-# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.39 2000/07/13 16:07:14 petere Exp $
+# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.40 2000/07/22 03:34:43 tgl Exp $
#
subdir = src/backend/utils/adt
@@ -15,7 +15,7 @@ CFLAGS+= -mieee
endif
endif
-OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o chunk.o \
+OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o \
date.o datetime.o datum.o filename.o float.o format_type.o \
geo_ops.o geo_selfuncs.o int.o int8.o like.o lztext.o \
misc.o nabstime.o name.o not_in.o numeric.o numutils.o \
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 907082a7268..b4bc71f349a 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* arrayfuncs.c
- * Special functions for arrays.
+ * Support functions for arrays.
*
* 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.61 2000/07/17 03:05:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.62 2000/07/22 03:34:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,15 +19,15 @@
#include "catalog/catalog.h"
#include "catalog/pg_type.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 "="
+#define RETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0)
+
+
/*
* An array has the following internal structure:
* <nbytes> - total number of bytes
@@ -36,41 +36,30 @@
* <dim> - size of each array axis
* <dim_lower> - lower boundary of each dimension
* <actual data> - whatever is the stored data
+ * The actual data starts on a MAXALIGN boundary.
*/
-static int _ArrayCount(char *str, int *dim, int typdelim);
+static int ArrayCount(char *str, int *dim, int typdelim);
static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
FmgrInfo *inputproc, Oid typelem, int32 typmod,
char typdelim, int typlen, bool typbyval,
char typalign, int *nbytes);
-#ifdef LOARRAY
-static char *_ReadLOArray(char *str, int *nbytes, int *fd, bool *chunkFlag,
- int ndim, int *dim, int baseSize);
-#endif
static void CopyArrayEls(char *p, Datum *values, int nitems,
bool typbyval, int typlen, char typalign,
bool freedata);
static void system_cache_lookup(Oid element_type, bool input, int *typlen,
bool *typbyval, char *typdelim, Oid *typelem, Oid *proc,
char *typalign);
-static Datum _ArrayCast(char *value, bool byval, int len);
-
-#ifdef LOARRAY
-static char *_AdvanceBy1word(char *str, char **word);
-
-#endif
-static void _ArrayRange(int *st, int *endp, int bsize, char *destPtr,
- ArrayType *array, int from);
-static int _ArrayClipCount(int *stI, int *endpI, ArrayType *array);
-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 Datum ArrayCast(char *value, bool byval, int len);
+static void ArrayClipCopy(int *st, int *endp, int bsize, char *destPtr,
+ ArrayType *array, bool from);
+static int ArrayClipCount(int *st, int *endp, ArrayType *array);
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 bool 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
@@ -153,8 +142,9 @@ array_in(PG_FUNCTION_ARGS)
{
if (*p == '{')
{
- ndim = _ArrayCount(p, dim, typdelim);
- for (i = 0; i < ndim; lBound[i++] = 1);
+ ndim = ArrayCount(p, dim, typdelim);
+ for (i = 0; i < ndim; i++)
+ lBound[i] = 1;
}
else
elog(ERROR, "array_in: Need to specify dimension");
@@ -179,71 +169,46 @@ array_in(PG_FUNCTION_ARGS)
printf(") for %s\n", string);
#endif
- nitems = getNitems(ndim, dim);
+ nitems = ArrayGetNItems(ndim, dim);
if (nitems == 0)
{
retval = (ArrayType *) palloc(sizeof(ArrayType));
MemSet(retval, 0, sizeof(ArrayType));
- *(int32 *) retval = sizeof(ArrayType);
+ retval->size = sizeof(ArrayType);
PG_RETURN_ARRAYTYPE_P(retval);
}
- if (*p == '{')
- {
- /* array not a large object */
- dataPtr = ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
- typmod, typdelim, typlen, typbyval, typalign,
- &nbytes);
- nbytes += ARR_OVERHEAD(ndim);
- retval = (ArrayType *) palloc(nbytes);
- MemSet(retval, 0, nbytes);
- retval->size = nbytes;
- retval->ndim = ndim;
- SET_LO_FLAG(false, retval);
- memcpy((char *) ARR_DIMS(retval), (char *) dim,
- ndim * sizeof(int));
- memcpy((char *) ARR_LBOUND(retval), (char *) lBound,
- ndim * sizeof(int));
-
- CopyArrayEls(ARR_DATA_PTR(retval), dataPtr, nitems,
- typbyval, typlen, typalign, true);
- pfree(dataPtr);
- }
- else
- {
-#ifdef LOARRAY
- int dummy,
- bytes;
- bool chunked = false;
-
- dataPtr = _ReadLOArray(p, &bytes, &dummy, &chunked, ndim,
- dim, typlen);
- nbytes = bytes + ARR_OVERHEAD(ndim);
- retval = (ArrayType *) palloc(nbytes);
- MemSet(retval, 0, nbytes);
- retval->size = nbytes;
- retval->ndim = ndim;
- SET_LO_FLAG(true, retval);
- SET_CHUNK_FLAG(chunked, retval);
- memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int));
- memmove((char *) ARR_LBOUND(retval), (char *) lBound, ndim * sizeof(int));
- memmove(ARR_DATA_PTR(retval), dataPtr, bytes);
-#endif
- elog(ERROR, "large object arrays not supported");
- PG_RETURN_NULL();
- }
+ if (*p != '{')
+ elog(ERROR, "array_in: missing left brace");
+
+ dataPtr = ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
+ typmod, typdelim, typlen, typbyval, typalign,
+ &nbytes);
+ nbytes += ARR_OVERHEAD(ndim);
+ retval = (ArrayType *) palloc(nbytes);
+ MemSet(retval, 0, nbytes);
+ retval->size = nbytes;
+ retval->ndim = ndim;
+ memcpy((char *) ARR_DIMS(retval), (char *) dim,
+ ndim * sizeof(int));
+ memcpy((char *) ARR_LBOUND(retval), (char *) lBound,
+ ndim * sizeof(int));
+
+ CopyArrayEls(ARR_DATA_PTR(retval), dataPtr, nitems,
+ typbyval, typlen, typalign, true);
+ pfree(dataPtr);
pfree(string_save);
PG_RETURN_ARRAYTYPE_P(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
*-----------------------------------------------------------------------------
*/
static int
-_ArrayCount(char *str, int *dim, int typdelim)
+ArrayCount(char *str, int *dim, int typdelim)
{
int nest_level = 0,
i;
@@ -411,7 +376,7 @@ ReadArrayStr(char *arrayStr,
if (!scanning_string)
{
if (i == -1)
- i = tuple2linear(ndim, indx, prod);
+ i = ArrayGetOffset0(ndim, indx, prod);
nest_level--;
if (nest_level == 0)
eoArray = done = true;
@@ -426,7 +391,7 @@ ReadArrayStr(char *arrayStr,
if (*q == typdelim && !scanning_string)
{
if (i == -1)
- i = tuple2linear(ndim, indx, prod);
+ i = ArrayGetOffset0(ndim, indx, prod);
done = true;
indx[ndim - 1]++;
}
@@ -491,79 +456,6 @@ ReadArrayStr(char *arrayStr,
}
-/*----------------------------------------------------------------------------
- * Read data about an array to be stored as a large object
- *----------------------------------------------------------------------------
- */
-#ifdef LOARRAY
-static char *
-_ReadLOArray(char *str,
- int *nbytes,
- int *fd,
- bool *chunkFlag,
- int ndim,
- int *dim,
- int baseSize)
-{
- char *inputfile,
- *accessfile = NULL,
- *chunkfile = NULL;
- char *retStr,
- *_AdvanceBy1word();
- Oid lobjId;
-
- str = _AdvanceBy1word(str, &inputfile);
-
- while (str != NULL)
- {
- char *word;
-
- str = _AdvanceBy1word(str, &word);
-
- if (!strcmp(word, "-chunk"))
- {
- if (str == NULL)
- elog(ERROR, "array_in: access pattern file required");
- str = _AdvanceBy1word(str, &accessfile);
- }
- else if (!strcmp(word, "-noreorg"))
- {
- if (str == NULL)
- elog(ERROR, "array_in: chunk file required");
- str = _AdvanceBy1word(str, &chunkfile);
- }
- else
- elog(ERROR, "usage: <input file> -chunk DEFAULT/<access pattern file> -invert/-native [-noreorg <chunk file>]");
- }
-
- if (inputfile == NULL)
- elog(ERROR, "array_in: missing file name");
- 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;
- *nbytes = strlen(retStr) + 2;
-
- if (accessfile)
- {
- FILE *afd;
-
- 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,
- chunkfile);
- FreeFile(afd);
- }
- return retStr;
-}
-
-#endif
-
/*----------
* Copy data into an array object from a temporary array of Datums.
*
@@ -634,34 +526,13 @@ array_out(PG_FUNCTION_ARGS)
int ndim,
*dim;
- if (ARR_IS_LO(v) == true)
- {
- text *p;
- int plen,
- nbytes;
-
- p = (text *) DatumGetPointer(DirectFunctionCall1(array_dims,
- PointerGetDatum(v)));
- plen = VARSIZE(p) - VARHDRSZ;
-
- /* get a wide string to print to */
- nbytes = strlen(ARR_DATA_PTR(v)) + strlen(ASSGN) + plen + 1;
- retval = (char *) palloc(nbytes);
-
- memcpy(retval, VARDATA(p), plen);
- strcpy(retval + plen, ASSGN);
- strcat(retval, ARR_DATA_PTR(v));
- pfree(p);
- PG_RETURN_CSTRING(retval);
- }
-
system_cache_lookup(element_type, false, &typlen, &typbyval,
&typdelim, &typelem, &typoutput, &typalign);
fmgr_info(typoutput, &outputproc);
sprintf(delim, "%c", typdelim);
ndim = ARR_NDIM(v);
dim = ARR_DIMS(v);
- nitems = getNitems(ndim, dim);
+ nitems = ArrayGetNItems(ndim, dim);
if (nitems == 0)
{
@@ -814,7 +685,6 @@ array_dims(PG_FUNCTION_ARGS)
*/
result = (text *) palloc(nbytes + VARHDRSZ);
- MemSet(result, 0, nbytes + VARHDRSZ);
p = VARDATA(result);
dimv = ARR_DIMS(v);
@@ -846,143 +716,87 @@ array_ref(ArrayType *array,
int arraylen,
bool *isNull)
{
- int i,
- ndim,
+ int ndim,
*dim,
*lb,
- offset,
- nbytes;
- struct varlena *v = NULL;
- Datum result;
- char *retval;
+ offset;
+ char *retptr;
if (array == (ArrayType *) NULL)
RETURN_NULL(Datum);
+
if (arraylen > 0)
{
-
/*
- * fixed length arrays -- these are assumed to be 1-d
+ * fixed-length arrays -- these are assumed to be 1-d, 0-based
*/
- if (indx[0] * elmlen > arraylen)
- elog(ERROR, "array_ref: array bound exceeded");
- retval = (char *) array + indx[0] * elmlen;
- return _ArrayCast(retval, elmbyval, elmlen);
+ if (nSubscripts != 1)
+ RETURN_NULL(Datum);
+ if (indx[0] < 0 || indx[0] * elmlen >= arraylen)
+ RETURN_NULL(Datum);
+ retptr = (char *) array + indx[0] * elmlen;
+ return ArrayCast(retptr, elmbyval, elmlen);
}
+
+ /* detoast input if necessary */
+ array = DatumGetArrayTypeP(PointerGetDatum(array));
+
+ ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- ndim = ARR_NDIM(array);
- nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
if (!SanityCheckInput(ndim, nSubscripts, dim, lb, indx))
RETURN_NULL(Datum);
- offset = GetOffset(nSubscripts, dim, lb, indx);
-
- if (ARR_IS_LO(array))
- {
- char *lo_name;
- int fd = 0;
-
- /* We are assuming fixed element lengths here */
- offset *= elmlen;
- 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(Datum);
-#endif
- if (ARR_IS_CHUNKED(array))
- v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull);
- else
- {
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fd),
- Int32GetDatum(offset),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(Datum);
-#ifdef LOARRAY
- v = (struct varlena *)
- DatumGetPointer(DirectFunctionCall2(loread,
- Int32GetDatum(fd),
- Int32GetDatum(elmlen)));
-#endif
- }
- if (*isNull)
- RETURN_NULL(Datum);
- if (VARSIZE(v) - VARHDRSZ < elmlen)
- RETURN_NULL(Datum);
- DirectFunctionCall1(lo_close, Int32GetDatum(fd));
- result = _ArrayCast((char *) VARDATA(v), elmbyval, elmlen);
- if (! elmbyval)
- { /* not by value */
- char *tempdata = palloc(elmlen);
-
- memcpy(tempdata, DatumGetPointer(result), elmlen);
- result = PointerGetDatum(tempdata);
- }
- pfree(v);
- return result;
- }
+ offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
- if (elmlen > 0)
- {
- offset = offset * elmlen;
- /* off the end of the array */
- if (nbytes - offset < 1)
- RETURN_NULL(Datum);
- retval = ARR_DATA_PTR(array) + offset;
- return _ArrayCast(retval, elmbyval, elmlen);
- }
- else
- {
- int bytes = nbytes;
+ retptr = array_seek(ARR_DATA_PTR(array), elmlen, offset);
- retval = ARR_DATA_PTR(array);
- i = 0;
- while (bytes > 0)
- {
- if (i == offset)
- return PointerGetDatum(retval);
- bytes -= INTALIGN(*(int32 *) retval);
- retval += INTALIGN(*(int32 *) retval);
- i++;
- }
- RETURN_NULL(Datum);
- }
+ return ArrayCast(retptr, elmbyval, elmlen);
}
/*-----------------------------------------------------------------------------
- * array_clip :
- * This routine takes an array and a range of indices (upperIndex and
+ * array_get_slice :
+ * This routine takes an array and a range of indices (upperIndex and
* lowerIndx), creates a new array structure for the referred elements
* and returns a pointer to it.
*-----------------------------------------------------------------------------
*/
ArrayType *
-array_clip(ArrayType *array,
- int nSubscripts,
- int *upperIndx,
- int *lowerIndx,
- bool elmbyval,
- int elmlen,
- bool *isNull)
+array_get_slice(ArrayType *array,
+ int nSubscripts,
+ int *upperIndx,
+ int *lowerIndx,
+ bool elmbyval,
+ int elmlen,
+ int arraylen,
+ bool *isNull)
{
int i,
ndim,
*dim,
- *lb,
- nbytes;
+ *lb;
ArrayType *newArr;
int bytes,
span[MAXDIM];
- /* timer_start(); */
if (array == (ArrayType *) NULL)
RETURN_NULL(ArrayType *);
+
+ if (arraylen > 0)
+ {
+ /*
+ * fixed-length arrays -- no can do slice...
+ */
+ elog(ERROR, "Slices of fixed-length arrays not implemented");
+ }
+
+ /* detoast input if necessary */
+ array = DatumGetArrayTypeP(PointerGetDatum(array));
+
+ ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- ndim = ARR_NDIM(array);
- nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
if (!SanityCheckInput(ndim, nSubscripts, dim, lb, upperIndx) ||
!SanityCheckInput(ndim, nSubscripts, dim, lb, lowerIndx))
@@ -990,116 +804,40 @@ array_clip(ArrayType *array,
for (i = 0; i < nSubscripts; i++)
if (lowerIndx[i] > upperIndx[i])
- elog(ERROR, "lowerIndex cannot be larger than upperIndx");
- mda_get_range(nSubscripts, span, lowerIndx, upperIndx);
-
- if (ARR_IS_LO(array))
- {
-#ifdef LOARRAY
- char *lo_name;
-
-#endif
- char *newname = NULL;
- int fd = 0,
- newfd = 0,
- isDestLO = true,
- rsize;
-
- 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(ArrayType *);
- newname = _array_newLO(&newfd, Unix);
-#endif
- bytes = strlen(newname) + 1 + ARR_OVERHEAD(nSubscripts);
- newArr = (ArrayType *) palloc(bytes);
- newArr->size = bytes;
- newArr->ndim = array->ndim;
- newArr->flags = array->flags;
- memcpy(ARR_DIMS(newArr), span, nSubscripts * sizeof(int));
- memcpy(ARR_LBOUND(newArr), lowerIndx, nSubscripts * sizeof(int));
- strcpy(ARR_DATA_PTR(newArr), newname);
-
- rsize = compute_size(lowerIndx, upperIndx, nSubscripts, elmlen);
- if (rsize < BLCKSZ)
- {
- char *buff;
- rsize += VARHDRSZ;
- buff = palloc(rsize);
- if (buff)
- isDestLO = false;
- if (ARR_IS_CHUNKED(array))
- {
- _ReadChunkArray(lowerIndx, upperIndx, elmlen, fd, &(buff[VARHDRSZ]),
- array, 0, isNull);
- }
- else
- {
- _ReadArray(lowerIndx, upperIndx, elmlen, fd, (int) &(buff[VARHDRSZ]),
- array,
- 0, isNull);
- }
- memmove(buff, &rsize, VARHDRSZ);
-#ifdef LOARRAY
- if (!*isNull)
- bytes = DatumGetInt32(DirectFunctionCall2(lowrite,
- Int32GetDatum(newfd),
- PointerGetDatum(buff)));
-#endif
- pfree(buff);
- }
- if (isDestLO)
- {
- if (ARR_IS_CHUNKED(array))
- {
- _ReadChunkArray(lowerIndx, upperIndx, elmlen, fd, (char *) newfd, array,
- 1, isNull);
- }
- else
- _ReadArray(lowerIndx, upperIndx, elmlen, fd, newfd, array, 1, isNull);
- }
-#ifdef LOARRAY
- LOclose(fd);
- LOclose(newfd);
-#endif
- if (*isNull)
- {
- pfree(newArr);
- newArr = NULL;
- }
- /* timer_end(); */
- return newArr;
- }
+ mda_get_range(nSubscripts, span, lowerIndx, upperIndx);
if (elmlen > 0)
- {
- bytes = getNitems(nSubscripts, span);
- bytes = bytes * elmlen + ARR_OVERHEAD(nSubscripts);
- }
+ bytes = ArrayGetNItems(nSubscripts, span) * elmlen;
else
- {
- bytes = _ArrayClipCount(lowerIndx, upperIndx, array);
- bytes += ARR_OVERHEAD(nSubscripts);
- }
+ bytes = ArrayClipCount(lowerIndx, upperIndx, array);
+ bytes += ARR_OVERHEAD(nSubscripts);
+
newArr = (ArrayType *) palloc(bytes);
newArr->size = bytes;
newArr->ndim = array->ndim;
newArr->flags = array->flags;
memcpy(ARR_DIMS(newArr), span, nSubscripts * sizeof(int));
memcpy(ARR_LBOUND(newArr), lowerIndx, nSubscripts * sizeof(int));
- _ArrayRange(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(newArr), array, 1);
+ ArrayClipCopy(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(newArr),
+ array, true);
+
return newArr;
}
/*-----------------------------------------------------------------------------
- * array_set :
+ * array_set :
* 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.
+ * A new array is returned, just like the old except for the one
+ * modified entry.
+ *
+ * NOTE: For assignments, we throw an error for silly subscripts etc,
+ * rather than returning a NULL as the fetch operations do. The reasoning
+ * is that returning a NULL would cause the user's whole array to be replaced
+ * with NULL, which will probably not make him happy.
*-----------------------------------------------------------------------------
*/
ArrayType *
@@ -1115,194 +853,154 @@ array_set(ArrayType *array,
int ndim,
*dim,
*lb,
- offset,
- nbytes;
- char *pos;
+ offset;
+ ArrayType *newarray;
+ char *elt_ptr;
+ int oldsize,
+ newsize,
+ oldlen,
+ newlen,
+ lth0,
+ lth1,
+ lth2;
if (array == (ArrayType *) NULL)
RETURN_NULL(ArrayType *);
+
if (arraylen > 0)
{
-
/*
- * fixed length arrays -- these are assumed to be 1-d
+ * fixed-length arrays -- these are assumed to be 1-d, 0-based
*/
- if (indx[0] * elmlen > arraylen)
- elog(ERROR, "array_ref: array bound exceeded");
- pos = (char *) array + indx[0] * elmlen;
- ArrayCastAndSet(dataValue, elmbyval, elmlen, pos);
- return array;
+ if (nSubscripts != 1)
+ elog(ERROR, "Invalid array subscripts");
+ if (indx[0] < 0 || indx[0] * elmlen >= arraylen)
+ elog(ERROR, "Invalid array subscripts");
+ newarray = (ArrayType *) palloc(arraylen);
+ memcpy(newarray, array, arraylen);
+ elt_ptr = (char *) newarray + indx[0] * elmlen;
+ ArrayCastAndSet(dataValue, elmbyval, elmlen, elt_ptr);
+ return newarray;
}
+
+ /* detoast input if necessary */
+ array = DatumGetArrayTypeP(PointerGetDatum(array));
+
+ ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- ndim = ARR_NDIM(array);
- nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
if (!SanityCheckInput(ndim, nSubscripts, dim, lb, indx))
- {
- elog(ERROR, "array_set: array bound exceeded");
- return array;
- }
- offset = GetOffset(nSubscripts, dim, lb, indx);
+ elog(ERROR, "Invalid array subscripts");
- if (ARR_IS_LO(array))
- {
- int fd = 0;
- struct varlena *v;
+ offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
- /* We are assuming fixed element lengths here */
- offset *= elmlen;
-#ifdef LOARRAY
- char *lo_name;
+ elt_ptr = array_seek(ARR_DATA_PTR(array), elmlen, offset);
- lo_name = ARR_DATA_PTR(array);
- if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
- return array;
-#endif
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fd),
- Int32GetDatum(offset),
- Int32GetDatum(SEEK_SET))) < 0)
- return array;
- v = (struct varlena *) palloc(elmlen + VARHDRSZ);
- VARATT_SIZEP(v) = elmlen + VARHDRSZ;
- ArrayCastAndSet(dataValue, elmbyval, elmlen, VARDATA(v));
-#ifdef LOARRAY
- if (DatumGetInt32(DirectFunctionCall2(lowrite,
- Int32GetDatum(fd),
- PointerGetDatum(v)))
- != elmlen)
- RETURN_NULL(ArrayType *);
-#endif
- pfree(v);
- DirectFunctionCall1(lo_close, Int32GetDatum(fd));
- return array;
- }
if (elmlen > 0)
{
- offset = offset * elmlen;
- /* off the end of the array */
- if (nbytes - offset < 1)
- return array;
- pos = ARR_DATA_PTR(array) + offset;
+ oldlen = newlen = elmlen;
}
else
{
- ArrayType *newarray;
- char *elt_ptr;
- int oldsize,
- newsize,
- oldlen,
- newlen,
- lth0,
- lth1,
- lth2;
-
- elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset);
+ /* varlena type */
oldlen = INTALIGN(*(int32 *) elt_ptr);
newlen = INTALIGN(*(int32 *) DatumGetPointer(dataValue));
-
- if (oldlen == newlen)
- {
- /* new element with same size, overwrite old data */
- ArrayCastAndSet(dataValue, elmbyval, elmlen, elt_ptr);
- return array;
- }
-
- /* new element with different size, reallocate the array */
- oldsize = array->size;
- 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(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 newarray;
}
- ArrayCastAndSet(dataValue, elmbyval, elmlen, pos);
- return array;
+
+ oldsize = ARR_SIZE(array);
+ lth0 = ARR_OVERHEAD(ndim);
+ lth1 = (int) (elt_ptr - ARR_DATA_PTR(array));
+ lth2 = (int) (oldsize - lth0 - lth1 - oldlen);
+ newsize = lth0 + lth1 + newlen + lth2;
+
+ newarray = (ArrayType *) palloc(newsize);
+ memcpy((char *) newarray, (char *) array, lth0 + lth1);
+ memcpy((char *) newarray + lth0 + lth1 + newlen,
+ (char *) array + lth0 + lth1 + oldlen, lth2);
+ newarray->size = newsize;
+ newlen = ArrayCastAndSet(dataValue, elmbyval, elmlen,
+ (char *) newarray + lth0 + lth1);
+
+ return newarray;
}
/*----------------------------------------------------------------------------
- * array_assgn :
+ * array_set_slice :
* This routine sets the value of a range of array locations (specified
* by upper and lower index values ) to new values passed as
* another array
* result :
- * returns a pointer to the modified array.
+ * A new array is returned, just like the old except for the
+ * modified range.
+ *
+ * NOTE: For assignments, we throw an error for silly subscripts etc,
+ * rather than returning a NULL as the fetch operations do. The reasoning
+ * is that returning a NULL would cause the user's whole array to be replaced
+ * with NULL, which will probably not make him happy.
*----------------------------------------------------------------------------
*/
ArrayType *
-array_assgn(ArrayType *array,
- int nSubscripts,
- int *upperIndx,
- int *lowerIndx,
- ArrayType *newArr,
- bool elmbyval,
- int elmlen,
- bool *isNull)
+array_set_slice(ArrayType *array,
+ int nSubscripts,
+ int *upperIndx,
+ int *lowerIndx,
+ ArrayType *srcArray,
+ bool elmbyval,
+ int elmlen,
+ int arraylen,
+ bool *isNull)
{
int i,
ndim,
*dim,
*lb;
+ int span[MAXDIM];
if (array == (ArrayType *) NULL)
RETURN_NULL(ArrayType *);
+ if (srcArray == (ArrayType *) NULL)
+ RETURN_NULL(ArrayType *);
+
+ if (arraylen > 0)
+ {
+ /*
+ * fixed-length arrays -- no can do slice...
+ */
+ elog(ERROR, "Updates on slices of fixed-length arrays not implemented");
+ }
+
+ /* detoast array, making sure we get an overwritable copy */
+ array = DatumGetArrayTypePCopy(PointerGetDatum(array));
+
+ /* detoast source array if necessary */
+ srcArray = DatumGetArrayTypeP(PointerGetDatum(srcArray));
+
if (elmlen < 0)
- elog(ERROR, "array_assgn: updates on arrays of variable length elements not implemented");
+ elog(ERROR, "Updates on slices of arrays of variable length elements not implemented");
+ ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- ndim = ARR_NDIM(array);
if (!SanityCheckInput(ndim, nSubscripts, dim, lb, upperIndx) ||
!SanityCheckInput(ndim, nSubscripts, dim, lb, lowerIndx))
- RETURN_NULL(ArrayType *);
+ elog(ERROR, "Invalid array subscripts");
for (i = 0; i < nSubscripts; i++)
if (lowerIndx[i] > upperIndx[i])
- elog(ERROR, "lowerIndex larger than upperIndx");
+ elog(ERROR, "Invalid array subscripts");
- if (ARR_IS_LO(array))
- {
- int fd = 0,
- newfd = 0;
+ /* make sure source array has enough entries */
+ mda_get_range(ndim, span, lowerIndx, upperIndx);
-#ifdef LOARRAY
- char *lo_name;
+ if (ArrayGetNItems(ndim, span) >
+ ArrayGetNItems(ARR_NDIM(srcArray), ARR_DIMS(srcArray)))
+ elog(ERROR, "Source array too small");
+
+ ArrayClipCopy(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(srcArray),
+ array, false);
- lo_name = (char *) ARR_DATA_PTR(array);
- if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
- 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 array;
-#endif
- _LOArrayRange(lowerIndx, upperIndx, elmlen, fd, newfd, array, 1, isNull);
- DirectFunctionCall1(lo_close, Int32GetDatum(newfd));
- }
- else
- {
- _LOArrayRange(lowerIndx, upperIndx, elmlen, fd, (int) ARR_DATA_PTR(newArr),
- array, 0, isNull);
- }
- DirectFunctionCall1(lo_close, Int32GetDatum(fd));
- return array;
- }
- _ArrayRange(lowerIndx, upperIndx, elmlen, ARR_DATA_PTR(newArr), array, 0);
return array;
}
@@ -1337,7 +1035,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
ArrayType *v;
ArrayType *result;
Datum *values;
- char *elt;
+ Datum elt;
int *dim;
int ndim;
int nitems;
@@ -1360,13 +1058,9 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
elog(ERROR, "array_map: null input array");
v = PG_GETARG_ARRAYTYPE_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);
+ nitems = ArrayGetNItems(ndim, dim);
/* Check for empty array */
if (nitems <= 0)
@@ -1380,7 +1074,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
/* Allocate temporary array for new values */
values = (Datum *) palloc(nitems * sizeof(Datum));
- MemSet(values, 0, nitems * sizeof(Datum));
/* Loop over source data */
s = (char *) ARR_DATA_PTR(v);
@@ -1392,22 +1085,25 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
switch (inp_typlen)
{
case 1:
- elt = (char *) ((int) (*(char *) s));
+ elt = CharGetDatum(*s);
break;
case 2:
- elt = (char *) ((int) (*(int16 *) s));
+ elt = Int16GetDatum(*(int16 *) s);
break;
- case 3:
case 4:
+ elt = Int32GetDatum(*(int32 *) s);
+ break;
default:
- elt = (char *) (*(int32 *) s);
+ elog(ERROR, "array_map: unsupported byval length %d",
+ inp_typlen);
+ elt = 0; /* keep compiler quiet */
break;
}
s += inp_typlen;
}
else
{
- elt = s;
+ elt = PointerGetDatum(s);
if (inp_typlen > 0)
s += inp_typlen;
else
@@ -1421,7 +1117,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
* whether fn() is strict. Would need to do more work here
* to support arrays containing nulls, too.
*/
- fcinfo->arg[0] = (Datum) elt;
+ fcinfo->arg[0] = elt;
fcinfo->argnull[0] = false;
fcinfo->isnull = false;
values[i] = FunctionCallInvoke(fcinfo);
@@ -1524,7 +1220,7 @@ deconstruct_array(ArrayType *array,
char *p;
int i;
- nelems = getNitems(ARR_NDIM(array), ARR_DIMS(array));
+ nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
if (nelems <= 0)
{
*elemsp = NULL;
@@ -1570,6 +1266,8 @@ deconstruct_array(ArrayType *array,
* compares two arrays for equality
* result :
* returns true if the arrays are equal, false otherwise.
+ *
+ * XXX bitwise equality is pretty bogus ...
*-----------------------------------------------------------------------------
*/
Datum
@@ -1577,17 +1275,25 @@ array_eq(PG_FUNCTION_ARGS)
{
ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1);
+ bool result = true;
+
+ if (ARR_SIZE(array1) != ARR_SIZE(array2))
+ result = false;
+ else if (memcmp(array1, array2, ARR_SIZE(array1)) != 0)
+ result = false;
- if (*(int32 *) array1 != *(int32 *) array2)
- PG_RETURN_BOOL(false);
- if (memcmp(array1, array2, *(int32 *) array1) != 0)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(true);
+ /* Avoid leaking memory when handed toasted input. */
+ PG_FREE_IF_COPY(array1, 0);
+ PG_FREE_IF_COPY(array2, 1);
+
+ PG_RETURN_BOOL(result);
}
+
/***************************************************************************/
/******************| Support Routines |*****************/
/***************************************************************************/
+
static void
system_cache_lookup(Oid element_type,
bool input,
@@ -1620,28 +1326,26 @@ system_cache_lookup(Oid element_type,
*proc = typeStruct->typoutput;
}
+/* Fetch array value at pointer, converted correctly to a Datum */
static Datum
-_ArrayCast(char *value, bool byval, int len)
+ArrayCast(char *value, bool byval, int len)
{
- if (byval)
+ if (! byval)
+ return PointerGetDatum(value);
+
+ switch (len)
{
- switch (len)
- {
- case 1:
- return (Datum) *value;
- case 2:
- return (Datum) *(int16 *) value;
- case 3:
- case 4:
- return (Datum) *(int32 *) value;
- default:
- elog(ERROR, "array_ref: byval and elt len > 4!");
- break;
- }
+ case 1:
+ return CharGetDatum(*value);
+ case 2:
+ return Int16GetDatum(*(int16 *) value);
+ case 4:
+ return Int32GetDatum(*(int32 *) value);
+ default:
+ elog(ERROR, "ArrayCast: unsupported byval length %d", len);
+ break;
}
- else
- return (Datum) value;
- return 0;
+ return 0; /* keep compiler quiet */
}
/*
@@ -1673,7 +1377,8 @@ ArrayCastAndSet(Datum src,
*(int32 *) dest = DatumGetInt32(src);
break;
default:
- elog(ERROR, "ArrayCastAndSet: unexpected typlen");
+ elog(ERROR, "ArrayCastAndSet: unsupported byval length %d",
+ typlen);
break;
}
/* For by-val types, assume no alignment padding is needed */
@@ -1693,55 +1398,32 @@ ArrayCastAndSet(Datum src,
/* XXX WRONG: should use MAXALIGN or type's alignment requirement */
inc = INTALIGN(VARSIZE(DatumGetPointer(src)));
}
- return inc;
-}
-#ifdef LOARRAY
-static char *
-_AdvanceBy1word(char *str, char **word)
-{
- char *retstr,
- *space;
-
- *word = NULL;
- if (str == NULL)
- return str;
- while (isspace(*str))
- str++;
- *word = str;
- if ((space = (char *) strchr(str, ' ')) != (char *) NULL)
- {
- retstr = space + 1;
- *space = '\0';
- }
- else
- retstr = NULL;
- return retstr;
+ return inc;
}
-#endif
-
-static int
+/* Do Sanity check on input subscripting info */
+static bool
SanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx)
{
int i;
- /* Do Sanity check on input */
- if (n != ndim)
- return 0;
+ if (n != ndim || ndim <= 0 || ndim > MAXDIM)
+ return false;
for (i = 0; i < ndim; i++)
if ((lb[i] > indx[i]) || (indx[i] >= (dim[i] + lb[i])))
- return 0;
- return 1;
+ return false;
+ return true;
}
+/* Copy an array slice into or out of an array */
static void
-_ArrayRange(int *st,
- int *endp,
- int bsize,
- char *destPtr,
- ArrayType *array,
- int from)
+ArrayClipCopy(int *st,
+ int *endp,
+ int bsize,
+ char *destPtr,
+ ArrayType *array,
+ bool from)
{
int n,
*dim,
@@ -1759,16 +1441,14 @@ _ArrayRange(int *st,
n = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- srcPtr = ARR_DATA_PTR(array);
- for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
+ st_pos = ArrayGetOffset(n, dim, lb, st);
+ srcPtr = array_seek(ARR_DATA_PTR(array), bsize, st_pos);
mda_get_prod(n, dim, prod);
- st_pos = tuple2linear(n, st, prod);
- srcPtr = array_seek(srcPtr, bsize, st_pos);
mda_get_range(n, span, st, endp);
mda_get_offset_values(n, dist, prod, span);
- for (i = 0; i < n; indx[i++] = 0);
- i = j = n - 1;
- inc = bsize;
+ for (i = 0; i < n; i++)
+ indx[i] = 0;
+ j = n - 1;
do
{
srcPtr = array_seek(srcPtr, bsize, dist[j]);
@@ -1778,11 +1458,12 @@ _ArrayRange(int *st,
inc = array_read(srcPtr, bsize, 1, destPtr);
destPtr += inc;
srcPtr += inc;
- } while ((j = next_tuple(i + 1, indx, span)) != -1);
+ } while ((j = mda_next_tuple(n, indx, span)) != -1);
}
+/* Compute space needed for an array slice of varlena items */
static int
-_ArrayClipCount(int *stI, int *endpI, ArrayType *array)
+ArrayClipCount(int *st, int *endp, ArrayType *array)
{
int n,
*dim,
@@ -1794,34 +1475,32 @@ _ArrayClipCount(int *stI, int *endpI, ArrayType *array)
indx[MAXDIM];
int i,
j,
- inc,
- st[MAXDIM],
- endp[MAXDIM];
+ inc;
int count = 0;
char *ptr;
n = ARR_NDIM(array);
dim = ARR_DIMS(array);
lb = ARR_LBOUND(array);
- ptr = ARR_DATA_PTR(array);
- for (i = 0; i < n; st[i] = stI[i] - lb[i], endp[i] = endpI[i] - lb[i], i++);
+ st_pos = ArrayGetOffset(n, dim, lb, st);
+ ptr = array_seek(ARR_DATA_PTR(array), -1, st_pos);
mda_get_prod(n, dim, prod);
- st_pos = tuple2linear(n, st, prod);
- ptr = array_seek(ptr, -1, st_pos);
mda_get_range(n, span, st, endp);
mda_get_offset_values(n, dist, prod, span);
- for (i = 0; i < n; indx[i++] = 0);
- i = j = n - 1;
+ for (i = 0; i < n; i++)
+ indx[i] = 0;
+ j = n - 1;
do
{
ptr = array_seek(ptr, -1, dist[j]);
inc = INTALIGN(*(int32 *) ptr);
ptr += inc;
count += inc;
- } while ((j = next_tuple(i + 1, indx, span)) != -1);
+ } while ((j = mda_next_tuple(n, indx, span)) != -1);
return count;
}
+/* Advance over nitems array elements */
static char *
array_seek(char *ptr, int eltsize, int nitems)
{
@@ -1834,6 +1513,7 @@ array_seek(char *ptr, int eltsize, int nitems)
return ptr;
}
+/* Copy nitems array elements from srcptr to destptr */
static int
array_read(char *destptr, int eltsize, int nitems, char *srcptr)
{
@@ -1846,7 +1526,8 @@ array_read(char *destptr, int eltsize, int nitems, char *srcptr)
memmove(destptr, srcptr, eltsize * nitems);
return eltsize * nitems;
}
- for (i = inc = 0; i < nitems; i++)
+ inc = 0;
+ for (i = 0; i < nitems; i++)
{
tmp = (INTALIGN(*(int32 *) srcptr));
memmove(destptr, srcptr, tmp);
@@ -1856,199 +1537,3 @@ array_read(char *destptr, int eltsize, int nitems, char *srcptr)
}
return inc;
}
-
-static void
-_LOArrayRange(int *st,
- int *endp,
- int bsize,
- int srcfd,
- int destfd,
- ArrayType *array,
- int isSrcLO,
- bool *isNull)
-{
- int n,
- *dim,
- st_pos,
- prod[MAXDIM];
- int span[MAXDIM],
- dist[MAXDIM],
- indx[MAXDIM];
- int i,
- j,
- inc,
- tmp,
- *lb,
- offset;
-
- n = ARR_NDIM(array);
- dim = ARR_DIMS(array);
- lb = ARR_LBOUND(array);
- for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
-
- mda_get_prod(n, dim, prod);
- st_pos = tuple2linear(n, st, prod);
- offset = st_pos * bsize;
- 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);
- for (i = 0; i < n; indx[i++] = 0);
- for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--])
- if (dist[i])
- break;
- j = n - 1;
- do
- {
- offset += (dist[j] * bsize);
- 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)
- return;
- offset += inc;
- } while ((j = next_tuple(i + 1, indx, span)) != -1);
-}
-
-
-static void
-_ReadArray(int *st,
- int *endp,
- int bsize,
- int srcfd,
- int destfd,
- ArrayType *array,
- int isDestLO,
- bool *isNull)
-{
- int n,
- *dim,
- st_pos,
- prod[MAXDIM];
- int span[MAXDIM],
- dist[MAXDIM],
- indx[MAXDIM];
- int i,
- j,
- inc,
- tmp,
- *lb,
- offset;
-
- n = ARR_NDIM(array);
- dim = ARR_DIMS(array);
- lb = ARR_LBOUND(array);
- for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
-
- mda_get_prod(n, dim, prod);
- st_pos = tuple2linear(n, st, prod);
- offset = st_pos * bsize;
- 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);
- for (i = 0; i < n; indx[i++] = 0);
- for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--])
- if (dist[i])
- break;
- j = n - 1;
- do
- {
- offset += (dist[j] * bsize);
- 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)
- return;
- offset += inc;
- } while ((j = next_tuple(i + 1, indx, span)) != -1);
-}
-
-
-int
-_LOtransfer(char **destfd,
- int size,
- int nitems,
- char **srcfd,
- int isSrcLO,
- 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;
-
- inc = nitems * size;
- if (isSrcLO && isDestLO && inc > 0)
- for (tmp = 0, resid = inc;
- resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc)
- {
-#ifdef LOARRAY
- v = (struct varlena *)
- DatumGetPointer(DirectFunctionCall2(loread,
- Int32GetDatum((int32) *srcfd),
- Int32GetDatum(inc)));
- if (VARSIZE(v) - VARHDRSZ < inc)
- {
- pfree(v);
- return -1;
- }
- tmp += DatumGetInt32(DirectFunctionCall2(lowrite,
- Int32GetDatum((int32) *destfd),
- PointerGetDatum(v)));
-#endif
- pfree(v);
-
- }
- else if (!isSrcLO && isDestLO)
- {
- tmp = lo_write((int) *destfd, *srcfd, inc);
- *srcfd = *srcfd + tmp;
- }
- else if (isSrcLO && !isDestLO)
- {
- tmp = lo_read((int) *srcfd, *destfd, inc);
- *destfd = *destfd + tmp;
- }
- else
- {
- memmove(*destfd, *srcfd, inc);
- tmp = inc;
- *srcfd += inc;
- *destfd += inc;
- }
- return tmp;
-#undef MAX_READ
-}
-
-char *
-_array_newLO(int *fd, int flag)
-{
- char *p;
- char saveName[NAME_LEN];
-
- p = (char *) palloc(NAME_LEN);
- sprintf(p, "/Arry.%u", newoid());
- strcpy(saveName, p);
-#ifdef LOARRAY
- if ((*fd = LOcreat(saveName, 0600, flag)) < 0)
- elog(ERROR, "Large object create failed");
-#endif
- return p;
-}
diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c
index 3293cecc960..d103d8b885b 100644
--- a/src/backend/utils/adt/arrayutils.c
+++ b/src/backend/utils/adt/arrayutils.c
@@ -8,61 +8,62 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayutils.c,v 1.10 2000/01/26 05:57:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayutils.c,v 1.11 2000/07/22 03:34:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-#define WEAK_C_OPTIMIZER
-
#include "postgres.h"
+
#include "utils/array.h"
+
+
+/* Convert subscript list into linear element number (from 0) */
int
-GetOffset(int n, int *dim, int *lb, int *indx)
+ArrayGetOffset(int n, int *dim, int *lb, int *indx)
{
int i,
- scale,
- offset;
+ scale = 1,
+ offset = 0;
- for (i = n - 1, scale = 1, offset = 0; i >= 0; scale *= dim[i--])
+ for (i = n - 1; i >= 0; i--)
+ {
offset += (indx[i] - lb[i]) * scale;
+ scale *= dim[i];
+ }
return offset;
}
+/* Same, but subscripts are assumed 0-based, and use a scale array
+ * instead of raw dimension data (see mda_get_prod to create scale array)
+ */
int
-getNitems(int n, int *a)
+ArrayGetOffset0(int n, int *tup, int *scale)
{
int i,
- ret;
+ lin = 0;
- for (i = 0, ret = 1; i < n; ret *= a[i++]);
- if (n == 0)
- ret = 0;
- return ret;
+ for (i = 0; i < n; i++)
+ lin += tup[i] * scale[i];
+ return lin;
}
+/* Convert array dimensions into number of elements */
int
-compute_size(int *st, int *endp, int n, int base)
+ArrayGetNItems(int n, int *a)
{
int i,
ret;
- for (i = 0, ret = base; i < n; i++)
- ret *= (endp[i] - st[i] + 1);
+ if (n <= 0)
+ return 0;
+ ret = 1;
+ for (i = 0; i < n; i++)
+ ret *= a[i];
return ret;
}
-void
-mda_get_offset_values(int n, int *dist, int *PC, int *span)
-{
- int i,
- j;
-
- for (j = n - 2, dist[n - 1] = 0; j >= 0; j--)
- for (i = j + 1, dist[j] = PC[j] - 1; i < n;
- dist[j] -= (span[i] - 1) * PC[i], i++);
-}
-
+/* Compute ranges (sub-array dimensions) for an array slice */
void
mda_get_range(int n, int *span, int *st, int *endp)
{
@@ -72,56 +73,59 @@ mda_get_range(int n, int *span, int *st, int *endp)
span[i] = endp[i] - st[i] + 1;
}
+/* Compute products of array dimensions, ie, scale factors for subscripts */
void
-mda_get_prod(int n, int *range, int *P)
+mda_get_prod(int n, int *range, int *prod)
{
int i;
- for (i = n - 2, P[n - 1] = 1; i >= 0; i--)
- P[i] = P[i + 1] * range[i + 1];
-}
-
-int
-tuple2linear(int n, int *tup, int *scale)
-{
- int i,
- lin;
-
- for (i = lin = 0; i < n; i++)
- lin += tup[i] * scale[i];
- return lin;
+ prod[n - 1] = 1;
+ for (i = n - 2; i >= 0; i--)
+ prod[i] = prod[i + 1] * range[i + 1];
}
+/* From products of whole-array dimensions and spans of a sub-array,
+ * compute offset distances needed to step through subarray within array
+ */
void
-array2chunk_coord(int n, int *C, int *a_coord, int *c_coord)
+mda_get_offset_values(int n, int *dist, int *prod, int *span)
{
- int i;
+ int i,
+ j;
- for (i = 0; i < n; i++)
- c_coord[i] = a_coord[i] / C[i];
+ dist[n - 1] = 0;
+ for (j = n - 2; j >= 0; j--)
+ {
+ dist[j] = prod[j] - 1;
+ for (i = j + 1; i < n; i++)
+ dist[j] -= (span[i] - 1) * prod[i];
+ }
}
/*-----------------------------------------------------------------------------
generates the tuple that is lexicographically one greater than the current
n-tuple in "curr", with the restriction that the i-th element of "curr" is
less than the i-th element of "span".
- RETURNS 0 if no next tuple exists
- 1 otherwise
- -----------------------------------------------------------------------------*/
+ Returns -1 if no next tuple exists, else the subscript position (0..n-1)
+ corresponding to the dimension to advance along.
+ -----------------------------------------------------------------------------
+*/
int
-next_tuple(int n, int *curr, int *span)
+mda_next_tuple(int n, int *curr, int *span)
{
int i;
- if (!n)
+ if (n <= 0)
return -1;
+
curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
- for (i = n - 1; i * (!curr[i]); i--)
+ for (i = n - 1; i && curr[i] == 0; i--)
curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
if (i)
return i;
if (curr[0])
return 0;
+
return -1;
}
diff --git a/src/backend/utils/adt/chunk.c b/src/backend/utils/adt/chunk.c
deleted file mode 100644
index 55776769493..00000000000
--- a/src/backend/utils/adt/chunk.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * chunk.c
- *
- * 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/Attic/chunk.c,v 1.28 2000/06/18 22:44:13 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <ctype.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include "postgres.h"
-
-#include "catalog/pg_type.h"
-#include "fmgr.h"
-#include "libpq/be-fsstubs.h"
-#include "libpq/libpq-fs.h"
-#include "utils/array.h"
-#include "utils/memutils.h"
-
-#define INFTY 500000000
-#define MANY 10000
-#define MAXPAT 20
-#define quot_ceil(x,y) (((x)+(y)-1)/(y))
-#if !defined(min)
-#define min(x,y) (((x) < (y))? (x) : (y))
-#endif
-#if !defined(max)
-#define max(x,y) (((x) > (y))? (x) : (y))
-#endif
-
-static CHUNK_INFO cInfo;
-
-/* non-export function prototypes */
-static int _FindBestChunk(int size, int *dmax, int *dbest, int dim,
- int A[MAXPAT][MAXDIM + 1], int N);
-static int get_next(int *d, int k, int C, int *dmax);
-static void initialize_info(CHUNK_INFO *A, int ndim, int *dim, int *chunk);
-
-#ifdef LOARRAY
-static void _ConvertToChunkFile(int n, int baseSize, int *dim, int *C,
- int srcfd, int destfd);
-static void read_chunk(int *chunk_no, int *C, char *a_chunk, int srcfd,
- int n, int baseSize, int *PX, int *dist);
-static int write_chunk(struct varlena * a_chunk, int ofile);
-static int seek_and_read(int pos, int size, char *buff, int fp, int from);
-
-#endif
-static int GetChunkSize(FILE *fd, int ndim, int dim[MAXDIM], int baseSize,
- int d[MAXDIM]);
-
-/*------------------------------------------------------------------------
- * _ChunkArray ---
- * converts an input array to chunked format using the information
- * provided by the access pattern.
- * Results:
- * creates a new file that stores the chunked array and returns
- * information about the chunked file
- *-----------------------------------------------------------------------
- */
-char *
-_ChunkArray(int fd,
- FILE *afd,
- int ndim,
- int *dim,
- int baseSize,
- int *nbytes,
- char *chunkfile)
-{
-#ifdef LOARRAY
- int cfd = 0;
-
-#endif
- int chunk[MAXDIM],
- csize;
- bool reorgFlag;
-
- if (chunkfile == NULL)
- reorgFlag = true;
- else
- reorgFlag = false;
-
-#ifdef LOARRAY
- if (reorgFlag)
- /* create new LO for chunked file */
- chunkfile = _array_newLO(&cfd, fileFlag);
- else
- cfd = LOopen(chunkfile, O_RDONLY);
- if (cfd < 0)
- elog(ERROR, "Unable to open chunk file");
-#endif
-
- strcpy(cInfo.lo_name, chunkfile);
-
- /* find chunk size */
- csize = GetChunkSize(afd, ndim, dim, baseSize, chunk);
-
-#ifdef LOARRAY
- if (reorgFlag)
- /* copy data from input file to chunked file */
- _ConvertToChunkFile(ndim, baseSize, dim, chunk, fd, cfd);
-#endif
-
- initialize_info(&cInfo, ndim, dim, chunk);
- *nbytes = sizeof(CHUNK_INFO);
- return (char *) &cInfo;
-}
-
-/*--------------------------------------------------------------------------
- * GetChunkSize
- * given an access pattern and array dimensionality etc, this program
- * returns the dimensions of the chunk in "d"
- *-----------------------------------------------------------------------
- */
-static int
-GetChunkSize(FILE *fd,
- int ndim,
- int dim[MAXDIM],
- int baseSize,
- int d[MAXDIM])
-{
- int N,
- i,
- j,
- csize;
- int A[MAXPAT][MAXDIM + 1],
- dmax[MAXDIM];
-
- /*
- * ----------- read input ------------
- */
- fscanf(fd, "%d", &N);
- if (N > MAXPAT)
- elog(ERROR, "array_in: too many access pattern elements");
- for (i = 0; i < N; i++)
- for (j = 0; j < ndim + 1; j++)
- if (fscanf(fd, "%d ", &(A[i][j])) == EOF)
- elog(ERROR, "array_in: bad access pattern input");
-
- /*
- * estimate chunk size
- */
- for (i = 0; i < ndim; i++)
- for (j = 0, dmax[i] = 1; j < N; j++)
- if (dmax[i] < A[j][i])
- dmax[i] = A[j][i];
- csize = BLCKSZ / baseSize;
-
- _FindBestChunk(csize, dmax, d, ndim, A, N);
-
- return csize;
-}
-
-/*-------------------------------------------------------------------------
- * _FindBestChunk
- * This routine does most of the number crunching to compute the
- * optimal chunk shape.
- * Called by GetChunkSize
- *------------------------------------------------------------------------
- */
-static int
-_FindBestChunk(int size,
- int *dmax,
- int *dbest,
- int dim,
- int A[MAXPAT][MAXDIM + 1],
- int N)
-{
- int d[MAXDIM];
- int tc,
- mintc = INFTY;
-
- d[0] = 0;
- mintc = INFTY;
- while (get_next(d, dim, size, dmax))
- {
-
- /*
- * compute the number of page fetches for a given chunk size (*d)
- * and access pattern (**A)
- */
- int i,
- j,
- nc;
-
- for (i = 0, tc = 0; i < N; i++)
- {
- for (j = 0, nc = 1; j < dim; j++)
- nc *= quot_ceil(A[i][j], d[j]);
- nc *= A[i][dim];
- tc += nc;
- }
-
- /*
- * tc holds the total number of page fetches
- */
- if (mintc >= tc)
- {
- mintc = tc;
- for (j = 0; j < dim; dbest[j] = d[j], j++)
- ;
- }
- }
- return mintc;
-}
-
-/*----------------------------------------------------------------------
- * get_next
- * Called by _GetBestChunk to get the next tuple in the lexicographic order
- *---------------------------------------------------------------------
- */
-static int
-get_next(int *d, int k, int C, int *dmax)
-{
- int i,
- j,
- temp;
-
- if (!d[0])
- {
- temp = C;
- for (j = k - 1; j >= 0; j--)
- {
- d[j] = min(temp, dmax[j]);
- temp = max(1, temp / d[j]);
- }
- return 1;
- }
-
- for (j = 0, temp = 1; j < k; j++)
- temp *= d[j];
-
- for (i = k - 1; i >= 0; i--)
- {
- temp = temp / d[i];
- if (((temp * (d[i] + 1)) < C) && (d[i] + 1 <= dmax[i]))
- break;
- }
- if (i < 0)
- return 0;
-
- d[i]++;
- j = C / temp;
- d[i] = min(dmax[i], j / (j / d[i]));
- temp = temp * d[i];
- temp = C / temp;
-
- for (j = k - 1; j > i; j--)
- {
- d[j] = min(temp, dmax[j]);
- temp = max(1, temp / d[j]);
- }
- return 1;
-}
-
-#ifdef LOARRAY
-static char a_chunk[BLCKSZ + VARHDRSZ]; /* VARHDRSZ since a_chunk is in
- * varlena format */
-
-#endif
-
-static void
-initialize_info(CHUNK_INFO *A, int ndim, int *dim, int *chunk)
-{
- int i;
-
- for (i = 0; i < ndim; i++)
- A->C[i] = chunk[i];
-}
-
-/*--------------------------------------------------------------------------
- * Procedure reorganize_data():
- * This procedure reads the input multidimensional array that is organised
- * in the order specified by array "X" and breaks it up into chunks of
- * dimensions specified in "C".
- *
- * This is a very slow process, since reading and writing of LARGE files
- * may be involved.
- *
- *-------------------------------------------------------------------------
- */
-#ifdef LOARRAY
-static void
-_ConvertToChunkFile(int n,
- int baseSize,
- int *dim,
- int *C,
- int srcfd,
- int destfd)
-{
- int max_chunks[MAXDIM],
- chunk_no[MAXDIM];
- int PX[MAXDIM],
- dist[MAXDIM];
- int csize = 1,
- i,
- temp;
-
- for (i = 0; i < n; chunk_no[i++] = 0)
- {
- max_chunks[i] = dim[i] / C[i];
- csize *= C[i];
- }
- csize *= baseSize;
- temp = csize + VARHDRSZ;
- memmove(a_chunk, &temp, VARHDRSZ);
-
- mda_get_prod(n, dim, PX);
- mda_get_offset_values(n, dist, PX, C);
- for (i = 0; i < n; dist[i] *= baseSize, i++)
- ;
- do
- {
- read_chunk(chunk_no, C, &(a_chunk[VARHDRSZ]), srcfd, n, baseSize, PX, dist);
- write_chunk((struct varlena *) a_chunk, destfd);
- } while (next_tuple(n, chunk_no, max_chunks) != -1);
-}
-
-/*--------------------------------------------------------------------------
- * read_chunk
- * reads a chunk from the input files into a_chunk, the position of the
- * chunk is specified by chunk_no
- *--------------------------------------------------------------------------
- */
-static void
-read_chunk(int *chunk_no,
- int *C,
- char *a_chunk,
- int srcfd,
- int n,
- int baseSize,
- int *PX,
- int *dist)
-{
- int i,
- j,
- cp,
- unit_transfer;
- int start_pos,
- pos[MAXDIM];
- int indx[MAXDIM];
- int fpOff;
-
- for (i = start_pos = 0; i < n; i++)
- {
- pos[i] = chunk_no[i] * C[i];
- start_pos += pos[i] * PX[i];
- }
- start_pos *= baseSize;
-
- /* Read a block of dimesion C starting at co-ordinates pos */
- unit_transfer = C[n - 1] * baseSize;
-
- for (i = 0; i < n; indx[i++] = 0)
- ;
- fpOff = start_pos;
- seek_and_read(fpOff, unit_transfer, a_chunk, srcfd, SEEK_SET);
- fpOff += unit_transfer;
- cp = unit_transfer;
-
- while ((j = next_tuple(n - 1, indx, C)) != -1)
- {
- fpOff += dist[j];
- seek_and_read(fpOff, unit_transfer, &(a_chunk[cp]), srcfd, SEEK_SET);
- cp += unit_transfer;
- fpOff += unit_transfer;
- }
-}
-
-/*--------------------------------------------------------------------------
- * write_chunk()
- * writes a chunk of size csize into the output file
- *--------------------------------------------------------------------------
- */
-static int
-write_chunk(struct varlena * a_chunk, int ofile)
-{
- int got_n = 0;
-
-#ifdef LOARRAY
- got_n = DatumGetInt32(DirectFunctionCall2(lowrite,
- Int32GetDatum(ofile),
- PointerGetDatum(a_chunk)));
-#endif
- return got_n;
-}
-
-/*--------------------------------------------------------------------------
- * seek_and_read()
- * seeks to the asked location in the input file and reads the
- * appropriate number of blocks
- * Called By: read_chunk()
- *--------------------------------------------------------------------------
- */
-static int
-seek_and_read(int pos, int size, char *buff, int fp, int from)
-{
- struct varlena *v;
-
- /* Assuming only one file */
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fp),
- Int32GetDatum(pos),
- Int32GetDatum(from))) < 0)
- elog(ERROR, "File seek error");
-#ifdef LOARRAY
- v = (struct varlena *)
- DatumGetPointer(DirectFunctionCall2(loread,
- Int32GetDatum(fp),
- Int32GetDatum(size)));
-#endif
- if (VARSIZE(v) - VARHDRSZ < size)
- elog(ERROR, "File read error");
- memmove(buff, VARDATA(v), size);
- pfree(v);
- return 1;
-
-}
-
-#endif /* LOARRAY */
-
-/*----------------------------------------------------------------------------
- * _ReadChunkArray
- * returns the subarray specified bu the range indices "st" and "endp"
- * from the chunked array stored in file "fp"
- *---------------------------------------------------------------------------
- */
-int
-_ReadChunkArray(int *st,
- int *endp,
- int bsize,
- int fp,
- char *destfp,
- ArrayType *array,
- int isDestLO,
- bool *isNull)
-{
- int i,
- j,
- jj;
- int n,
- temp,
- words_read;
- int chunk_span[MAXDIM],
- chunk_off[MAXDIM];
- int chunk_st[MAXDIM],
- chunk_end[MAXDIM];
- int block_seek;
-
- int bptr,
- *C,
- csize,
- *dim,
- *lb;
- int range_st[MAXDIM],
- range_end[MAXDIM],
- range[MAXDIM],
- array_span[MAXDIM];
- int PA[MAXDIM],
- PCHUNK[MAXDIM],
- PC[MAXDIM];
- int to_read;
- int cdist[MAXDIM],
- adist[MAXDIM];
- int dist[MAXDIM],
- temp_seek;
-
- int srcOff; /* Needed since LO don't understand
- * SEEK_CUR */
- char *baseDestFp = (char *) destfp;
-
- CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array);
-
- n = ARR_NDIM(array);
- dim = ARR_DIMS(array);
- lb = ARR_LBOUND(array);
- C = A->C;
-
- csize = C[n - 1];
- PC[n - 1] = 1;
- temp = dim[n - 1] / C[n - 1];
- for (i = n - 2; i >= 0; i--)
- {
- PC[i] = PC[i + 1] * temp;
- temp = dim[i] / C[i];
- csize *= C[i];
- }
-
- for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++)
- ;
- mda_get_prod(n, C, PCHUNK);
- mda_get_range(n, array_span, st, endp);
- mda_get_prod(n, array_span, PA);
-
- array2chunk_coord(n, C, st, chunk_st);
- array2chunk_coord(n, C, endp, chunk_end);
- mda_get_range(n, chunk_span, chunk_st, chunk_end);
- mda_get_offset_values(n, dist, PC, chunk_span);
-
- for (i = 0; i < n; i++)
- {
- range_st[i] = st[i];
- range_end[i] = min(chunk_st[i] * C[i] + C[i] - 1, endp[i]);
- }
-
- for (i = j = 0; i < n; i++)
- j += chunk_st[i] * PC[i];
- temp_seek = srcOff = j * csize * bsize;
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fp),
- Int32GetDatum(srcOff),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(int);
-
- jj = n - 1;
- for (i = 0; i < n; chunk_off[i++] = 0)
- ;
- words_read = 0;
- temp_seek = 0;
- do
- {
- /* Write chunk (chunk_st) to output buffer */
- mda_get_range(n, array_span, range_st, range_end);
- mda_get_offset_values(n, adist, PA, array_span);
- mda_get_offset_values(n, cdist, PCHUNK, array_span);
- for (i = 0; i < n; range[i] = range_st[i] - st[i], i++);
- bptr = tuple2linear(n, range, PA);
- for (i = 0; i < n; range[i++] = 0);
- j = n - 1;
- bptr *= bsize;
- if (isDestLO)
- {
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum((int32) destfp),
- Int32GetDatum(bptr),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(int);
- }
- else
- destfp = baseDestFp + bptr;
- for (i = 0, block_seek = 0; i < n; i++)
- block_seek += (range_st[i] - (chunk_st[i] + chunk_off[i])
- * C[i]) * PCHUNK[i];
- if (dist[jj] + block_seek + temp_seek)
- {
- temp = (dist[jj] * csize + block_seek + temp_seek) * bsize;
- srcOff += temp;
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fp),
- Int32GetDatum(srcOff),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(int);
- }
- for (i = n - 1, to_read = bsize; i >= 0;
- to_read *= min(C[i], array_span[i]), i--)
- if (cdist[i] || adist[i])
- break;
- do
- {
- if (cdist[j])
- {
- srcOff += (cdist[j] * bsize);
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fp),
- Int32GetDatum(srcOff),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(int);
- }
- block_seek += cdist[j];
- bptr += adist[j] * bsize;
- if (isDestLO)
- {
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum((int32) destfp),
- Int32GetDatum(bptr),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(int);
- }
- else
- destfp = baseDestFp + bptr;
- temp = _LOtransfer((char **) &destfp, to_read, 1, (char **) &fp, 1, isDestLO);
- if (temp < to_read)
- RETURN_NULL(int);
- srcOff += to_read;
- words_read += to_read;
- bptr += to_read;
- block_seek += (to_read / bsize);
-
- /*
- * compute next tuple in *range
- */
- {
- int x;
-
- if (!(i + 1))
- j = -1;
- else
- {
- range[i] = (range[i] + 1) % array_span[i];
- for (x = i; x * (!range[x]); x--)
- range[x - 1] = (range[x - 1] + 1) % array_span[x - 1];
- if (x)
- j = x;
- else
- {
- if (range[0])
- j = 0;
- else
- j = -1;
- }
- }
- }
-
- /*
- * end of compute next tuple -- j is set to -1 if tuple
- * generation is over
- */
- } while (j != -1);
-
- block_seek = csize - block_seek;
- temp_seek = block_seek;
- jj = next_tuple(n, chunk_off, chunk_span);
- if (jj == -1)
- break;
- range_st[jj] = (chunk_st[jj] + chunk_off[jj]) * C[jj];
- range_end[jj] = min(range_st[jj] + C[jj] - 1, endp[jj]);
-
- for (i = jj + 1; i < n; i++)
- {
- range_st[i] = st[i];
- range_end[i] = min((chunk_st[i] + chunk_off[i]) * C[i] + C[i] - 1, endp[i]);
- }
- } while (jj != -1);
- return words_read;
-}
-
-/*------------------------------------------------------------------------
- * _ReadChunkArray1El
- * returns one element of the chunked array as specified by the index "st"
- * the chunked file descriptor is "fp"
- *-------------------------------------------------------------------------
- */
-struct varlena *
-_ReadChunkArray1El(int *st,
- int bsize,
- int fp,
- ArrayType *array,
- bool *isNull)
-{
- int i,
- j,
- n,
- temp,
- srcOff;
- int chunk_st[MAXDIM];
-
- int *C,
- csize,
- *dim,
- *lb;
- int PCHUNK[MAXDIM],
- PC[MAXDIM];
-
- CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array);
-
- n = ARR_NDIM(array);
- lb = ARR_LBOUND(array);
- C = A->C;
- dim = ARR_DIMS(array);
-
- csize = C[n - 1];
- PC[n - 1] = 1;
- temp = dim[n - 1] / C[n - 1];
- for (i = n - 2; i >= 0; i--)
- {
- PC[i] = PC[i + 1] * temp;
- temp = dim[i] / C[i];
- csize *= C[i];
- }
-
- for (i = 0; i < n; st[i] -= lb[i], i++);
- mda_get_prod(n, C, PCHUNK);
-
- array2chunk_coord(n, C, st, chunk_st);
-
- for (i = j = 0; i < n; i++)
- j += chunk_st[i] * PC[i];
- srcOff = j * csize;
-
- for (i = 0; i < n; i++)
- srcOff += (st[i] - chunk_st[i] * C[i]) * PCHUNK[i];
-
- srcOff *= bsize;
- if (DatumGetInt32(DirectFunctionCall3(lo_lseek,
- Int32GetDatum(fp),
- Int32GetDatum(srcOff),
- Int32GetDatum(SEEK_SET))) < 0)
- RETURN_NULL(struct varlena *);
-#ifdef LOARRAY
- return (struct varlena *)
- DatumGetPointer(DirectFunctionCall2(loread,
- Int32GetDatum(fp),
- Int32GetDatum(bsize)));
-#endif
- return (struct varlena *) 0;
-}
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index c77c3c40943..d14f9287e24 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_type.h,v 1.92 2000/07/07 19:24:41 petere Exp $
+ * $Id: pg_type.h,v 1.93 2000/07/22 03:34:28 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -76,11 +76,11 @@ CATALOG(pg_type) BOOTSTRAP
* If typelem is not 0 then it identifies another row in pg_type.
* The current type can then be subscripted like an array yielding
* values of type typelem. A non-zero typelem does not guarantee
- * this type to be an array type; ordinary fixed-length types can
- * also be subscripted (e.g., oidvector). Variable-length types
- * can *not* be turned into pseudo-arrays like that. Hence, the
- * way to determine whether a type is an array type is typelem !=
- * 0 and typlen < 0.
+ * this type to be a "real" array type; some ordinary fixed-length
+ * types can also be subscripted (e.g., oidvector). Variable-length
+ * types can *not* be turned into pseudo-arrays like that. Hence,
+ * the way to determine whether a type is a "true" array type is
+ * typelem != 0 and typlen < 0.
*/
Oid typelem;
regproc typinput;
@@ -282,7 +282,7 @@ DESCR("filename used in system tables");
DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
-DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ ));
DESCR("");
/* OIDS 700 - 799 */
@@ -309,11 +309,11 @@ DESCR("");
DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
-DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x _null_ ));
DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
-DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i p _null_ ));
+DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x _null_ ));
/* OIDS 800 - 899 */
DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ ));
@@ -328,34 +328,34 @@ DESCR("network IP address/netmask, network address");
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
-DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d p _null_ ));
-DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1026 ( _filename PGUID -1 -1 f b t \054 0 605 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1026 ( _filename PGUID -1 -1 f b t \054 0 605 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
@@ -364,10 +364,10 @@ DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array
#define ACLITEMSIZE 8
DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
DESCR("access control list");
-DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i p _null_ ));
+DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x _null_ ));
DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i p _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
@@ -383,33 +383,33 @@ DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
-DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i p _null_ ));
-DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x _null_ ));
DATA(insert OID = 1184 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1184
-DATA(insert OID = 1185 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 1185 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
-DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1200 - 1299 */
-DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i p _null_ ));
+DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x _null_ ));
DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
-DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d p _null_ ));
+DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1500 - 1599 */
DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 zpbit_in zpbit_out zpbit_in zpbit_out i p _null_ ));
DESCR("fixed-length bit string");
#define ZPBITOID 1560
-DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i p _null_ ));
+DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x _null_ ));
DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i p _null_ ));
DESCR("fixed-length bit string");
#define VARBITOID 1562
-DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i p _null_ ));
+DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x _null_ ));
/* OIDS 1600 - 1699 */
DATA(insert OID = 1625 ( lztext PGUID -1 -1 f b t \054 0 0 lztextin lztextout lztextin lztextout i x _null_ ));
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 4d915e0665f..590e79f06d4 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -5,18 +5,18 @@
* following files:
* utils/adt/arrayfuncs.c
* utils/adt/arrayutils.c
- * utils/adt/chunk.c
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: array.h,v 1.26 2000/07/17 03:05:32 tgl Exp $
+ * $Id: array.h,v 1.27 2000/07/22 03:34:35 tgl Exp $
*
* NOTES
- * XXX the data array should be MAXALIGN'd -- notice that the array
- * allocation code does not allocate the extra space required for this,
- * even though the array-packing code does the MAXALIGNs.
+ * XXX the data array should be MAXALIGN'd -- currently we only INTALIGN
+ * which is NOT good enough for, eg, arrays of Interval. Changing this
+ * will break existing user tables so hold off until we have some other
+ * reason to break user tables (like WAL).
*
*-------------------------------------------------------------------------
*/
@@ -34,6 +34,7 @@ typedef struct
int32 size; /* total array size (varlena requirement) */
int ndim; /* # of dimensions */
int flags; /* implementation flags */
+ /* flags field is currently unused, always zero. */
} ArrayType;
/*
@@ -46,35 +47,8 @@ typedef struct
#define PG_RETURN_ARRAYTYPE_P(x) PG_RETURN_POINTER(x)
/*
- * bitmask of ArrayType flags field:
- * 1st bit - large object flag
- * 2nd bit - chunk flag (array is chunked if set)
- * 3rd,4th,&5th bit - large object type (used only if bit 1 is set)
- */
-#define ARR_LOB_FLAG (0x1)
-#define ARR_CHK_FLAG (0x2)
-#define ARR_OBJ_MASK (0x1c)
-
-#define ARR_SIZE(a) (((ArrayType *) a)->size)
-#define ARR_NDIM(a) (((ArrayType *) a)->ndim)
-#define ARR_FLAGS(a) (((ArrayType *) a)->flags)
-
-#define ARR_IS_LO(a) \
- (((ArrayType *) a)->flags & ARR_LOB_FLAG)
-#define SET_LO_FLAG(f,a) \
- (((ArrayType *) a)->flags |= ((f) ? ARR_LOB_FLAG : 0x0))
-
-#define ARR_IS_CHUNKED(a) \
- (((ArrayType *) a)->flags & ARR_CHK_FLAG)
-#define SET_CHUNK_FLAG(f,a) \
- (((ArrayType *) a)->flags |= ((f) ? ARR_CHK_FLAG : 0x0))
-
-#define ARR_OBJ_TYPE(a) \
- ((ARR_FLAGS(a) & ARR_OBJ_MASK) >> 2)
-#define SET_OBJ_TYPE(f,a) \
- ((ARR_FLAGS(a)&= ~ARR_OBJ_MASK), (ARR_FLAGS(a)|=((f<<2)&ARR_OBJ_MASK)))
-
-/*
+ * Access macros for array header fields.
+ *
* ARR_DIMS returns a pointer to an array of array dimensions (number of
* elements along the various array axes).
*
@@ -85,39 +59,27 @@ typedef struct
*
* Unlike C, the default lower bound is 1.
*/
+#define ARR_SIZE(a) (((ArrayType *) (a))->size)
+#define ARR_NDIM(a) (((ArrayType *) (a))->ndim)
+
#define ARR_DIMS(a) \
- ((int *) (((char *) a) + sizeof(ArrayType)))
+ ((int *) (((char *) (a)) + sizeof(ArrayType)))
#define ARR_LBOUND(a) \
- ((int *) (((char *) a) + sizeof(ArrayType) + \
- (sizeof(int) * (((ArrayType *) a)->ndim))))
-
-/*
- * Returns a pointer to the actual array data.
- */
-#define ARR_DATA_PTR(a) \
- (((char *) a) + \
- MAXALIGN(sizeof(ArrayType) + 2 * (sizeof(int) * (a)->ndim)))
+ ((int *) (((char *) (a)) + sizeof(ArrayType) + \
+ (sizeof(int) * ARR_NDIM(a))))
/*
* The total array header size for an array of dimension n (in bytes).
*/
#define ARR_OVERHEAD(n) \
- (MAXALIGN(sizeof(ArrayType) + 2 * (n) * sizeof(int)))
+ (MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (n)))
-/*------------------------------------------------------------------------
- * Miscellaneous helper definitions and routines for arrayfuncs.c
- *------------------------------------------------------------------------
+/*
+ * Returns a pointer to the actual array data.
*/
+#define ARR_DATA_PTR(a) \
+ (((char *) (a)) + ARR_OVERHEAD(ARR_NDIM(a)))
-#define RETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0)
-
-#define NAME_LEN 30
-
-typedef struct
-{
- char lo_name[NAME_LEN];
- int C[MAXDIM];
-} CHUNK_INFO;
/*
* prototypes for functions defined in arrayfuncs.c
@@ -134,13 +96,16 @@ extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
Datum dataValue,
bool elmbyval, int elmlen,
int arraylen, bool *isNull);
-extern ArrayType *array_clip(ArrayType *array, int nSubscripts,
- int *upperIndx, int *lowerIndx,
- bool elmbyval, int elmlen, bool *isNull);
-extern ArrayType *array_assgn(ArrayType *array, int nSubscripts,
- int *upperIndx, int *lowerIndx,
- ArrayType *newArr,
- bool elmbyval, int elmlen, bool *isNull);
+extern ArrayType *array_get_slice(ArrayType *array, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ bool elmbyval, int elmlen,
+ int arraylen, bool *isNull);
+extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ ArrayType *srcArray,
+ bool elmbyval, int elmlen,
+ int arraylen, bool *isNull);
+
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType);
extern ArrayType *construct_array(Datum *elems, int nelems,
@@ -149,35 +114,18 @@ extern void deconstruct_array(ArrayType *array,
bool elmbyval, int elmlen, char elmalign,
Datum **elemsp, int *nelemsp);
-extern int _LOtransfer(char **destfd, int size, int nitems, char **srcfd,
- int isSrcLO, int isDestLO);
-extern char *_array_newLO(int *fd, int flag);
-
/*
* prototypes for functions defined in arrayutils.c
- * [these names seem to be too generic. Add prefix for arrays? -- AY]
*/
-extern int GetOffset(int n, int *dim, int *lb, int *indx);
-extern int getNitems(int n, int *a);
-extern int compute_size(int *st, int *endp, int n, int base);
-extern void mda_get_offset_values(int n, int *dist, int *PC, int *span);
+extern int ArrayGetOffset(int n, int *dim, int *lb, int *indx);
+extern int ArrayGetOffset0(int n, int *tup, int *scale);
+extern int ArrayGetNItems(int n, int *a);
extern void mda_get_range(int n, int *span, int *st, int *endp);
-extern void mda_get_prod(int n, int *range, int *P);
-extern int tuple2linear(int n, int *tup, int *scale);
-extern void array2chunk_coord(int n, int *C, int *a_coord, int *c_coord);
-extern int next_tuple(int n, int *curr, int *span);
-
-/*
- * prototypes for functions defined in chunk.c
- */
-extern char *_ChunkArray(int fd, FILE *afd, int ndim, int *dim, int baseSize,
- int *nbytes, char *chunkfile);
-extern int _ReadChunkArray(int *st, int *endp, int bsize, int fp,
- char *destfp, ArrayType *array, int isDestLO, bool *isNull);
-extern struct varlena *_ReadChunkArray1El(int *st, int bsize, int fp,
- ArrayType *array, bool *isNull);
+extern void mda_get_prod(int n, int *range, int *prod);
+extern void mda_get_offset_values(int n, int *dist, int *prod, int *span);
+extern int mda_next_tuple(int n, int *curr, int *span);
#endif /* ARRAY_H */