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 :-().
This commit is contained in:
parent
ec37ea1cc1
commit
d0e17e2112
@ -47,15 +47,18 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
|
|||||||
FmgrInfo finfo;
|
FmgrInfo finfo;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if ((array == (ArrayType *) NULL)
|
if (array == (ArrayType *) NULL)
|
||||||
|| (ARR_IS_LO(array) == true))
|
|
||||||
{
|
{
|
||||||
/* elog(NOTICE, "array_iterator: array is null"); */
|
/* elog(NOTICE, "array_iterator: array is null"); */
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* detoast input if necessary */
|
||||||
|
array = DatumGetArrayTypeP(PointerGetDatum(array));
|
||||||
|
|
||||||
ndim = ARR_NDIM(array);
|
ndim = ARR_NDIM(array);
|
||||||
dim = ARR_DIMS(array);
|
dim = ARR_DIMS(array);
|
||||||
nitems = getNitems(ndim, dim);
|
nitems = ArrayGetNItems(ndim, dim);
|
||||||
if (nitems == 0)
|
if (nitems == 0)
|
||||||
{
|
{
|
||||||
/* elog(NOTICE, "array_iterator: nitems = 0"); */
|
/* elog(NOTICE, "array_iterator: nitems = 0"); */
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* 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_in", /* receive procedure */
|
||||||
"array_out", /* send procedure */
|
"array_out", /* send procedure */
|
||||||
typeName, /* element type name */
|
typeName, /* element type name */
|
||||||
defaultValue, /* default type value */
|
NULL, /* never a default type value */
|
||||||
false, /* never passed by value */
|
false, /* never passed by value */
|
||||||
alignment,
|
alignment, /* NB: must be 'i' or 'd' for arrays... */
|
||||||
'p'); /* ARRAY doesn't support TOAST yet */
|
'x'); /* ARRAY is always toastable */
|
||||||
|
|
||||||
pfree(shadow_type);
|
pfree(shadow_type);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* ExecEvalArrayRef
|
||||||
*
|
*
|
||||||
* This function takes an ArrayRef and returns a Const Node if it
|
* This function takes an ArrayRef and returns the extracted Datum
|
||||||
* is an array reference or returns the changed Array Node if it is
|
* if it's a simple reference, or the modified array value if it's
|
||||||
* an array assignment.
|
* 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
|
static Datum
|
||||||
ExecEvalArrayRef(ArrayRef *arrayRef,
|
ExecEvalArrayRef(ArrayRef *arrayRef,
|
||||||
@ -77,7 +83,8 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
|
|||||||
bool *isNull,
|
bool *isNull,
|
||||||
bool *isDone)
|
bool *isDone)
|
||||||
{
|
{
|
||||||
ArrayType *array_scanner;
|
ArrayType *array_source;
|
||||||
|
ArrayType *resultArray;
|
||||||
List *elt;
|
List *elt;
|
||||||
int i = 0,
|
int i = 0,
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -90,7 +97,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
|
|||||||
|
|
||||||
if (arrayRef->refexpr != NULL)
|
if (arrayRef->refexpr != NULL)
|
||||||
{
|
{
|
||||||
array_scanner = (ArrayType *)
|
array_source = (ArrayType *)
|
||||||
DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
|
DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
|
||||||
econtext,
|
econtext,
|
||||||
isNull,
|
isNull,
|
||||||
@ -110,7 +117,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
|
|||||||
* the INSERT column list. This is a kluge, but it's not real
|
* the INSERT column list. This is a kluge, but it's not real
|
||||||
* clear what the semantics ought to be...
|
* clear what the semantics ought to be...
|
||||||
*/
|
*/
|
||||||
array_scanner = NULL;
|
array_source = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(elt, arrayRef->refupperindexpr)
|
foreach(elt, arrayRef->refupperindexpr)
|
||||||
@ -162,43 +169,45 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
|
|||||||
if (*isNull)
|
if (*isNull)
|
||||||
return (Datum) NULL;
|
return (Datum) NULL;
|
||||||
|
|
||||||
if (array_scanner == NULL)
|
if (array_source == NULL)
|
||||||
return sourceData; /* XXX do something else? */
|
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)
|
if (lIndex == NULL)
|
||||||
return PointerGetDatum(array_set(array_scanner, i,
|
resultArray = array_set(array_source, i,
|
||||||
upper.indx,
|
upper.indx,
|
||||||
sourceData,
|
sourceData,
|
||||||
arrayRef->refelembyval,
|
arrayRef->refelembyval,
|
||||||
arrayRef->refelemlength,
|
arrayRef->refelemlength,
|
||||||
arrayRef->refattrlength,
|
arrayRef->refattrlength,
|
||||||
isNull));
|
isNull);
|
||||||
return PointerGetDatum(array_assgn(array_scanner, i,
|
else
|
||||||
upper.indx, lower.indx,
|
resultArray = array_set_slice(array_source, i,
|
||||||
(ArrayType *) DatumGetPointer(sourceData),
|
upper.indx, lower.indx,
|
||||||
arrayRef->refelembyval,
|
(ArrayType *) DatumGetPointer(sourceData),
|
||||||
arrayRef->refelemlength,
|
arrayRef->refelembyval,
|
||||||
isNull));
|
arrayRef->refelemlength,
|
||||||
|
arrayRef->refattrlength,
|
||||||
|
isNull);
|
||||||
|
return PointerGetDatum(resultArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lIndex == NULL)
|
if (lIndex == NULL)
|
||||||
return array_ref(array_scanner, i,
|
return array_ref(array_source, i,
|
||||||
upper.indx,
|
upper.indx,
|
||||||
arrayRef->refelembyval,
|
arrayRef->refelembyval,
|
||||||
arrayRef->refelemlength,
|
arrayRef->refelemlength,
|
||||||
arrayRef->refattrlength,
|
arrayRef->refattrlength,
|
||||||
isNull);
|
isNull);
|
||||||
return PointerGetDatum(array_clip(array_scanner, i,
|
else
|
||||||
|
{
|
||||||
|
resultArray = array_get_slice(array_source, i,
|
||||||
upper.indx, lower.indx,
|
upper.indx, lower.indx,
|
||||||
arrayRef->refelembyval,
|
arrayRef->refelembyval,
|
||||||
arrayRef->refelemlength,
|
arrayRef->refelemlength,
|
||||||
isNull));
|
arrayRef->refattrlength,
|
||||||
|
isNull);
|
||||||
|
return PointerGetDatum(resultArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Makefile for utils/adt
|
# 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
|
subdir = src/backend/utils/adt
|
||||||
@ -15,7 +15,7 @@ CFLAGS+= -mieee
|
|||||||
endif
|
endif
|
||||||
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 \
|
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 \
|
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 \
|
misc.o nabstime.o name.o not_in.o numeric.o numutils.o \
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -8,61 +8,62 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert subscript list into linear element number (from 0) */
|
||||||
int
|
int
|
||||||
GetOffset(int n, int *dim, int *lb, int *indx)
|
ArrayGetOffset(int n, int *dim, int *lb, int *indx)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
scale,
|
scale = 1,
|
||||||
offset;
|
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;
|
offset += (indx[i] - lb[i]) * scale;
|
||||||
|
scale *= dim[i];
|
||||||
|
}
|
||||||
return offset;
|
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
|
int
|
||||||
getNitems(int n, int *a)
|
ArrayGetOffset0(int n, int *tup, int *scale)
|
||||||
|
{
|
||||||
|
int i,
|
||||||
|
lin = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
lin += tup[i] * scale[i];
|
||||||
|
return lin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert array dimensions into number of elements */
|
||||||
|
int
|
||||||
|
ArrayGetNItems(int n, int *a)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
ret;
|
ret;
|
||||||
|
|
||||||
for (i = 0, ret = 1; i < n; ret *= a[i++]);
|
if (n <= 0)
|
||||||
if (n == 0)
|
return 0;
|
||||||
ret = 0;
|
ret = 1;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
ret *= a[i];
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* Compute ranges (sub-array dimensions) for an array slice */
|
||||||
compute_size(int *st, int *endp, int n, int base)
|
|
||||||
{
|
|
||||||
int i,
|
|
||||||
ret;
|
|
||||||
|
|
||||||
for (i = 0, ret = base; i < n; i++)
|
|
||||||
ret *= (endp[i] - st[i] + 1);
|
|
||||||
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++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mda_get_range(int n, int *span, int *st, int *endp)
|
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;
|
span[i] = endp[i] - st[i] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute products of array dimensions, ie, scale factors for subscripts */
|
||||||
void
|
void
|
||||||
mda_get_prod(int n, int *range, int *P)
|
mda_get_prod(int n, int *range, int *prod)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = n - 2, P[n - 1] = 1; i >= 0; i--)
|
prod[n - 1] = 1;
|
||||||
P[i] = P[i + 1] * range[i + 1];
|
for (i = n - 2; i >= 0; i--)
|
||||||
|
prod[i] = prod[i + 1] * range[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* From products of whole-array dimensions and spans of a sub-array,
|
||||||
tuple2linear(int n, int *tup, int *scale)
|
* compute offset distances needed to step through subarray within array
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mda_get_offset_values(int n, int *dist, int *prod, int *span)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
lin;
|
j;
|
||||||
|
|
||||||
for (i = lin = 0; i < n; i++)
|
dist[n - 1] = 0;
|
||||||
lin += tup[i] * scale[i];
|
for (j = n - 2; j >= 0; j--)
|
||||||
return lin;
|
{
|
||||||
}
|
dist[j] = prod[j] - 1;
|
||||||
|
for (i = j + 1; i < n; i++)
|
||||||
void
|
dist[j] -= (span[i] - 1) * prod[i];
|
||||||
array2chunk_coord(int n, int *C, int *a_coord, int *c_coord)
|
}
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
c_coord[i] = a_coord[i] / C[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
generates the tuple that is lexicographically one greater than the current
|
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
|
n-tuple in "curr", with the restriction that the i-th element of "curr" is
|
||||||
less than the i-th element of "span".
|
less than the i-th element of "span".
|
||||||
RETURNS 0 if no next tuple exists
|
Returns -1 if no next tuple exists, else the subscript position (0..n-1)
|
||||||
1 otherwise
|
corresponding to the dimension to advance along.
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
next_tuple(int n, int *curr, int *span)
|
mda_next_tuple(int n, int *curr, int *span)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!n)
|
if (n <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
curr[n - 1] = (curr[n - 1] + 1) % span[n - 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];
|
curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
|
||||||
|
|
||||||
if (i)
|
if (i)
|
||||||
return i;
|
return i;
|
||||||
if (curr[0])
|
if (curr[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* 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.
|
* If typelem is not 0 then it identifies another row in pg_type.
|
||||||
* The current type can then be subscripted like an array yielding
|
* The current type can then be subscripted like an array yielding
|
||||||
* values of type typelem. A non-zero typelem does not guarantee
|
* values of type typelem. A non-zero typelem does not guarantee
|
||||||
* this type to be an array type; ordinary fixed-length types can
|
* this type to be a "real" array type; some ordinary fixed-length
|
||||||
* also be subscripted (e.g., oidvector). Variable-length types
|
* types can also be subscripted (e.g., oidvector). Variable-length
|
||||||
* can *not* be turned into pseudo-arrays like that. Hence, the
|
* types can *not* be turned into pseudo-arrays like that. Hence,
|
||||||
* way to determine whether a type is an array type is typelem !=
|
* the way to determine whether a type is a "true" array type is
|
||||||
* 0 and typlen < 0.
|
* typelem != 0 and typlen < 0.
|
||||||
*/
|
*/
|
||||||
Oid typelem;
|
Oid typelem;
|
||||||
regproc typinput;
|
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_ ));
|
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)'");
|
DESCR("geometric line '(pt1,pt2)'");
|
||||||
#define LINEOID 628
|
#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("");
|
DESCR("");
|
||||||
|
|
||||||
/* OIDS 700 - 799 */
|
/* 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_ ));
|
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)'");
|
DESCR("geometric circle '(center,radius)'");
|
||||||
#define CIRCLEOID 718
|
#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_ ));
|
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");
|
DESCR("$d,ddd.cc, money");
|
||||||
#define CASHOID 790
|
#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 */
|
/* 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_ ));
|
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 900 - 999 */
|
||||||
|
|
||||||
/* OIDS 1000 - 1099 */
|
/* 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 = 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 x _null_ ));
|
||||||
/*
|
/*
|
||||||
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
|
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
|
||||||
* Thanks to some padding, this will be 8 on all platforms.
|
* 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
|
#define ACLITEMSIZE 8
|
||||||
DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
|
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");
|
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 = 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 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 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 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 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 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 x _null_ ));
|
||||||
DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i p _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");
|
DESCR("char(length), blank-padded string, fixed storage length");
|
||||||
#define BPCHAROID 1042
|
#define BPCHAROID 1042
|
||||||
@ -383,33 +383,33 @@ DESCR("hh:mm:ss, ANSI SQL time");
|
|||||||
#define TIMEOID 1083
|
#define TIMEOID 1083
|
||||||
|
|
||||||
/* OIDS 1100 - 1199 */
|
/* 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 = 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 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 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_ ));
|
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");
|
DESCR("date and time");
|
||||||
#define TIMESTAMPOID 1184
|
#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_ ));
|
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");
|
DESCR("@ <number> <units>, time interval");
|
||||||
#define INTERVALOID 1186
|
#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 */
|
/* 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_ ));
|
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");
|
DESCR("hh:mm:ss, ANSI SQL time");
|
||||||
#define TIMETZOID 1266
|
#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 */
|
/* 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_ ));
|
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");
|
DESCR("fixed-length bit string");
|
||||||
#define ZPBITOID 1560
|
#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_ ));
|
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");
|
DESCR("fixed-length bit string");
|
||||||
#define VARBITOID 1562
|
#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 */
|
/* OIDS 1600 - 1699 */
|
||||||
DATA(insert OID = 1625 ( lztext PGUID -1 -1 f b t \054 0 0 lztextin lztextout lztextin lztextout i x _null_ ));
|
DATA(insert OID = 1625 ( lztext PGUID -1 -1 f b t \054 0 0 lztextin lztextout lztextin lztextout i x _null_ ));
|
||||||
|
@ -5,18 +5,18 @@
|
|||||||
* following files:
|
* following files:
|
||||||
* utils/adt/arrayfuncs.c
|
* utils/adt/arrayfuncs.c
|
||||||
* utils/adt/arrayutils.c
|
* utils/adt/arrayutils.c
|
||||||
* utils/adt/chunk.c
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* XXX the data array should be MAXALIGN'd -- notice that the array
|
* XXX the data array should be MAXALIGN'd -- currently we only INTALIGN
|
||||||
* allocation code does not allocate the extra space required for this,
|
* which is NOT good enough for, eg, arrays of Interval. Changing this
|
||||||
* even though the array-packing code does the MAXALIGNs.
|
* 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) */
|
int32 size; /* total array size (varlena requirement) */
|
||||||
int ndim; /* # of dimensions */
|
int ndim; /* # of dimensions */
|
||||||
int flags; /* implementation flags */
|
int flags; /* implementation flags */
|
||||||
|
/* flags field is currently unused, always zero. */
|
||||||
} ArrayType;
|
} ArrayType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -46,35 +47,8 @@ typedef struct
|
|||||||
#define PG_RETURN_ARRAYTYPE_P(x) PG_RETURN_POINTER(x)
|
#define PG_RETURN_ARRAYTYPE_P(x) PG_RETURN_POINTER(x)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bitmask of ArrayType flags field:
|
* Access macros for array header fields.
|
||||||
* 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)))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ARR_DIMS returns a pointer to an array of array dimensions (number of
|
* ARR_DIMS returns a pointer to an array of array dimensions (number of
|
||||||
* elements along the various array axes).
|
* elements along the various array axes).
|
||||||
*
|
*
|
||||||
@ -85,39 +59,27 @@ typedef struct
|
|||||||
*
|
*
|
||||||
* Unlike C, the default lower bound is 1.
|
* Unlike C, the default lower bound is 1.
|
||||||
*/
|
*/
|
||||||
#define ARR_DIMS(a) \
|
#define ARR_SIZE(a) (((ArrayType *) (a))->size)
|
||||||
((int *) (((char *) a) + sizeof(ArrayType)))
|
#define ARR_NDIM(a) (((ArrayType *) (a))->ndim)
|
||||||
#define ARR_LBOUND(a) \
|
|
||||||
((int *) (((char *) a) + sizeof(ArrayType) + \
|
|
||||||
(sizeof(int) * (((ArrayType *) a)->ndim))))
|
|
||||||
|
|
||||||
/*
|
#define ARR_DIMS(a) \
|
||||||
* Returns a pointer to the actual array data.
|
((int *) (((char *) (a)) + sizeof(ArrayType)))
|
||||||
*/
|
#define ARR_LBOUND(a) \
|
||||||
#define ARR_DATA_PTR(a) \
|
((int *) (((char *) (a)) + sizeof(ArrayType) + \
|
||||||
(((char *) a) + \
|
(sizeof(int) * ARR_NDIM(a))))
|
||||||
MAXALIGN(sizeof(ArrayType) + 2 * (sizeof(int) * (a)->ndim)))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The total array header size for an array of dimension n (in bytes).
|
* The total array header size for an array of dimension n (in bytes).
|
||||||
*/
|
*/
|
||||||
#define ARR_OVERHEAD(n) \
|
#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
|
* prototypes for functions defined in arrayfuncs.c
|
||||||
@ -134,13 +96,16 @@ extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
|
|||||||
Datum dataValue,
|
Datum dataValue,
|
||||||
bool elmbyval, int elmlen,
|
bool elmbyval, int elmlen,
|
||||||
int arraylen, bool *isNull);
|
int arraylen, bool *isNull);
|
||||||
extern ArrayType *array_clip(ArrayType *array, int nSubscripts,
|
extern ArrayType *array_get_slice(ArrayType *array, int nSubscripts,
|
||||||
int *upperIndx, int *lowerIndx,
|
int *upperIndx, int *lowerIndx,
|
||||||
bool elmbyval, int elmlen, bool *isNull);
|
bool elmbyval, int elmlen,
|
||||||
extern ArrayType *array_assgn(ArrayType *array, int nSubscripts,
|
int arraylen, bool *isNull);
|
||||||
int *upperIndx, int *lowerIndx,
|
extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts,
|
||||||
ArrayType *newArr,
|
int *upperIndx, int *lowerIndx,
|
||||||
bool elmbyval, int elmlen, bool *isNull);
|
ArrayType *srcArray,
|
||||||
|
bool elmbyval, int elmlen,
|
||||||
|
int arraylen, bool *isNull);
|
||||||
|
|
||||||
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType);
|
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType);
|
||||||
|
|
||||||
extern ArrayType *construct_array(Datum *elems, int nelems,
|
extern ArrayType *construct_array(Datum *elems, int nelems,
|
||||||
@ -149,35 +114,18 @@ extern void deconstruct_array(ArrayType *array,
|
|||||||
bool elmbyval, int elmlen, char elmalign,
|
bool elmbyval, int elmlen, char elmalign,
|
||||||
Datum **elemsp, int *nelemsp);
|
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
|
* 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 ArrayGetOffset(int n, int *dim, int *lb, int *indx);
|
||||||
extern int getNitems(int n, int *a);
|
extern int ArrayGetOffset0(int n, int *tup, int *scale);
|
||||||
extern int compute_size(int *st, int *endp, int n, int base);
|
extern int ArrayGetNItems(int n, int *a);
|
||||||
extern void mda_get_offset_values(int n, int *dist, int *PC, int *span);
|
|
||||||
extern void mda_get_range(int n, int *span, int *st, int *endp);
|
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 void mda_get_prod(int n, int *range, int *prod);
|
||||||
extern int tuple2linear(int n, int *tup, int *scale);
|
extern void mda_get_offset_values(int n, int *dist, int *prod, int *span);
|
||||||
extern void array2chunk_coord(int n, int *C, int *a_coord, int *c_coord);
|
extern int mda_next_tuple(int n, int *curr, int *span);
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ARRAY_H */
|
#endif /* ARRAY_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user