Skip to content

Commit c7793a7

Browse files
committed
Ensure that values stored within arrays are not toasted, per
discussion on pghackers a few days ago.
1 parent 18f1382 commit c7793a7

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

src/backend/utils/adt/arrayfuncs.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.63 2000/07/23 01:35:58 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.64 2000/07/27 03:50:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -33,6 +33,12 @@
3333
* <dim_lower> - lower boundary of each dimension
3434
* <actual data> - whatever is the stored data
3535
* The actual data starts on a MAXALIGN boundary.
36+
*
37+
* NOTE: it is important that array elements of toastable datatypes NOT be
38+
* toasted, since the tupletoaster won't know they are there. (We could
39+
* support compressed toasted items; only out-of-line items are dangerous.
40+
* However, it seems preferable to store such items uncompressed and allow
41+
* the toaster to compress the whole array as one input.)
3642
*/
3743

3844

@@ -459,6 +465,8 @@ ReadArrayStr(char *arrayStr,
459465
{
460466
if (values[i] != (Datum) 0)
461467
{
468+
/* let's just make sure data is not toasted */
469+
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
462470
if (typalign == 'd')
463471
*nbytes += MAXALIGN(VARSIZE(DatumGetPointer(values[i])));
464472
else
@@ -485,6 +493,10 @@ ReadArrayStr(char *arrayStr,
485493
* typbyval, typlen, typalign: info about element datatype
486494
* freedata: if TRUE and element type is pass-by-ref, pfree data values
487495
* referenced by Datums after copying them.
496+
*
497+
* If the input data is of varlena type, the caller must have ensured that
498+
* the values are not toasted. (Doing it here doesn't work since the
499+
* caller has already allocated space for the array...)
488500
*----------
489501
*/
490502
static void
@@ -961,6 +973,10 @@ array_set(ArrayType *array,
961973
return newarray;
962974
}
963975

976+
/* make sure item to be inserted is not toasted */
977+
if (elmlen < 0)
978+
dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue));
979+
964980
/* detoast input if necessary */
965981
array = DatumGetArrayTypeP(PointerGetDatum(array));
966982

@@ -1120,6 +1136,8 @@ array_set_slice(ArrayType *array,
11201136
array = DatumGetArrayTypeP(PointerGetDatum(array));
11211137
srcArray = DatumGetArrayTypeP(PointerGetDatum(srcArray));
11221138

1139+
/* note: we assume srcArray contains no toasted elements */
1140+
11231141
ndim = ARR_NDIM(array);
11241142
if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
11251143
elog(ERROR, "Invalid array subscripts");
@@ -1368,12 +1386,14 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
13681386
if (fcinfo->isnull)
13691387
elog(ERROR, "array_map: cannot handle NULL in array");
13701388

1371-
/* Update total result size */
1372-
if (typbyval)
1389+
/* Ensure data is not toasted, and update total result size */
1390+
if (typbyval || typlen > 0)
13731391
nbytes += typlen;
13741392
else
1375-
nbytes += ((typlen > 0) ? typlen :
1376-
INTALIGN(VARSIZE(DatumGetPointer(values[i]))));
1393+
{
1394+
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
1395+
nbytes += INTALIGN(VARSIZE(DatumGetPointer(values[i])));
1396+
}
13771397
}
13781398

13791399
/* Allocate and initialize the result array */
@@ -1420,10 +1440,13 @@ construct_array(Datum *elems, int nelems,
14201440
}
14211441
else
14221442
{
1423-
/* varlena type */
1443+
/* varlena type ... make sure it is untoasted */
14241444
nbytes = 0;
14251445
for (i = 0; i < nelems; i++)
1446+
{
1447+
elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
14261448
nbytes += INTALIGN(VARSIZE(DatumGetPointer(elems[i])));
1449+
}
14271450
}
14281451

14291452
/* Allocate and initialize 1-D result array */

0 commit comments

Comments
 (0)