11
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.156 2009/04/15 23:30:33 alvherre Exp $
11
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.160 2009/06/22 04:37:18 tgl Exp $
13
13
*-------------------------------------------------------------------------
96
96
int typlen, bool typbyval, char typalign);
97
97
static int array_cmp(FunctionCallInfo fcinfo);
98
98
static ArrayType *create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes,
99
Oid elmtype, int dataoffset);
99
Oid elmtype, int dataoffset);
100
100
static ArrayType *array_fill_internal(ArrayType *dims, ArrayType *lbs,
101
Datum value, bool isnull, Oid elmtype,
102
FunctionCallInfo fcinfo);
101
Datum value, bool isnull, Oid elmtype,
102
FunctionCallInfo fcinfo);
4182
/* Use datumCopy to ensure pass-by-ref stuff is copied into mcontext */
4183
* Ensure pass-by-ref stuff is copied into mcontext; and detoast it too
4184
* if it's varlena. (You might think that detoasting is not needed here
4185
* because construct_md_array can detoast the array elements later.
4186
* However, we must not let construct_md_array modify the ArrayBuildState
4187
* because that would mean array_agg_finalfn damages its input, which
4188
* is verboten. Also, this way frequently saves one copying step.)
4183
4190
if (!disnull && !astate->typbyval)
4184
dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
4192
if (astate->typlen == -1)
4193
dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
4195
dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
4186
4198
astate->dvalues[astate->nelems] = dvalue;
4187
4199
astate->dnulls[astate->nelems] = disnull;
4306
4318
/* stuff done only on the first call of the function */
4307
4319
if (SRF_IS_FIRSTCALL())
4309
ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
4310
int reqdim = PG_GETARG_INT32(1);
4321
ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
4322
int reqdim = PG_GETARG_INT32(1);
4314
4326
/* create a function context for cross-call persistence */
4315
4327
funcctx = SRF_FIRSTCALL_INIT();
4375
4387
array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
4384
4396
if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
4386
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4387
errmsg("dimension array or low bound array cannot be NULL")));
4398
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4399
errmsg("dimension array or low bound array cannot be NULL")));
4389
4401
dims = PG_GETARG_ARRAYTYPE_P(1);
4390
lbs = PG_GETARG_ARRAYTYPE_P(2);
4402
lbs = PG_GETARG_ARRAYTYPE_P(2);
4392
4404
if (!PG_ARGISNULL(0))
4416
4428
array_fill(PG_FUNCTION_ARGS)
4424
4436
if (PG_ARGISNULL(1))
4426
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4427
errmsg("dimension array or low bound array cannot be NULL")));
4438
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4439
errmsg("dimension array or low bound array cannot be NULL")));
4429
4441
dims = PG_GETARG_ARRAYTYPE_P(1);
4451
4463
create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
4452
4464
Oid elmtype, int dataoffset)
4456
4468
result = (ArrayType *) palloc0(nbytes);
4457
4469
SET_VARSIZE(result, nbytes);
4469
4481
Datum value, bool isnull, Oid elmtype,
4470
4482
FunctionCallInfo fcinfo)
4481
ArrayMetaState *my_extra;
4493
ArrayMetaState *my_extra;
4484
4496
* Params checks
4486
4498
if (ARR_NDIM(dims) != 1)
4488
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4489
errmsg("wrong number of array subscripts"),
4490
errdetail("Dimension array must be one dimensional.")));
4500
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4501
errmsg("wrong number of array subscripts"),
4502
errdetail("Dimension array must be one dimensional.")));
4492
4504
if (ARR_LBOUND(dims)[0] != 1)
4494
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4495
errmsg("wrong range of array subscripts"),
4496
errdetail("Lower bound of dimension array must be one.")));
4506
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4507
errmsg("wrong range of array subscripts"),
4508
errdetail("Lower bound of dimension array must be one.")));
4498
4510
if (ARR_HASNULL(dims))
4500
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4501
errmsg("dimension values cannot be null")));
4512
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4513
errmsg("dimension values cannot be null")));
4503
4515
dimv = (int *) ARR_DATA_PTR(dims);
4504
4516
ndims = ARR_DIMS(dims)[0];
4518
4530
if (ARR_NDIM(lbs) != 1)
4520
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4521
errmsg("wrong number of array subscripts"),
4522
errdetail("Dimension array must be one dimensional.")));
4532
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4533
errmsg("wrong number of array subscripts"),
4534
errdetail("Dimension array must be one dimensional.")));
4524
4536
if (ARR_LBOUND(lbs)[0] != 1)
4526
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4527
errmsg("wrong range of array subscripts"),
4528
errdetail("Lower bound of dimension array must be one.")));
4538
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4539
errmsg("wrong range of array subscripts"),
4540
errdetail("Lower bound of dimension array must be one.")));
4530
4542
if (ARR_HASNULL(lbs))
4532
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4533
errmsg("dimension values cannot be null")));
4544
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4545
errmsg("dimension values cannot be null")));
4535
4547
if (ARR_DIMS(lbs)[0] != ndims)
4537
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4538
errmsg("wrong number of array subscripts"),
4539
errdetail("Low bound array has different size than dimensions array.")));
4549
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4550
errmsg("wrong number of array subscripts"),
4551
errdetail("Low bound array has different size than dimensions array.")));
4541
4553
lbsv = (int *) ARR_DATA_PTR(lbs);
4547
4559
for (i = 0; i < MAXDIM; i++)
4654
char *elemdataptr; /* this moves with nextelem */
4655
bits8 *arraynullsptr; /* this does not */
4666
char *elemdataptr; /* this moves with nextelem */
4667
bits8 *arraynullsptr; /* this does not */
4659
4671
} array_unnest_fctx;
4661
4673
FuncCallContext *funcctx;
4679
4691
* Get the array value and detoast if needed. We can't do this
4680
* earlier because if we have to detoast, we want the detoasted
4681
* copy to be in multi_call_memory_ctx, so it will go away when
4682
* we're done and not before. (If no detoast happens, we assume
4683
* the originally passed array will stick around till then.)
4692
* earlier because if we have to detoast, we want the detoasted copy
4693
* to be in multi_call_memory_ctx, so it will go away when we're done
4694
* and not before. (If no detoast happens, we assume the originally
4695
* passed array will stick around till then.)
4685
4697
arr = PG_GETARG_ARRAYTYPE_P(0);