mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
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:
@@ -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 \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
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,
|
||||
ret;
|
||||
|
||||
for (i = 0, ret = 1; i < n; ret *= a[i++]);
|
||||
if (n == 0)
|
||||
ret = 0;
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
ret = 1;
|
||||
for (i = 0; i < n; i++)
|
||||
ret *= a[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
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++);
|
||||
}
|
||||
|
||||
/* 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];
|
||||
prod[n - 1] = 1;
|
||||
for (i = n - 2; i >= 0; i--)
|
||||
prod[i] = prod[i + 1] * range[i + 1];
|
||||
}
|
||||
|
||||
int
|
||||
tuple2linear(int n, int *tup, int *scale)
|
||||
/* From products of whole-array dimensions and spans of a sub-array,
|
||||
* 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,
|
||||
lin;
|
||||
j;
|
||||
|
||||
for (i = lin = 0; i < n; i++)
|
||||
lin += tup[i] * scale[i];
|
||||
return lin;
|
||||
}
|
||||
|
||||
void
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user