~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-security

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/arrayfuncs.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-11 16:59:35 UTC
  • mfrom: (5.1.1 karmic)
  • Revision ID: james.westby@ubuntu.com-20090711165935-jfwin6gfrxf0gfsi
Tags: 8.4.0-2
* debian/libpq-dev.install: Ship catalog/genbki.h. (Closes: #536139)
* debian/rules: Drop --enable-cassert for final release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 *
9
9
 *
10
10
 * IDENTIFICATION
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 $
12
12
 *
13
13
 *-------------------------------------------------------------------------
14
14
 */
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);
103
103
 
104
104
 
105
105
/*
1532
1532
 
1533
1533
/*
1534
1534
 * array_ndims :
1535
 
 *        returns the number of dimensions of the array pointed to by "v"
 
1535
 *                returns the number of dimensions of the array pointed to by "v"
1536
1536
 */
1537
1537
Datum
1538
1538
array_ndims(PG_FUNCTION_ARGS)
4179
4179
                }
4180
4180
        }
4181
4181
 
4182
 
        /* Use datumCopy to ensure pass-by-ref stuff is copied into mcontext */
 
4182
        /*
 
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.)
 
4189
         */
4183
4190
        if (!disnull && !astate->typbyval)
4184
 
                dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
 
4191
        {
 
4192
                if (astate->typlen == -1)
 
4193
                        dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
 
4194
                else
 
4195
                        dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
 
4196
        }
4185
4197
 
4186
4198
        astate->dvalues[astate->nelems] = dvalue;
4187
4199
        astate->dnulls[astate->nelems] = disnull;
4287
4299
 
4288
4300
typedef struct generate_subscripts_fctx
4289
4301
{
4290
 
        int4    lower;
4291
 
        int4    upper;
4292
 
        bool    reverse;
 
4302
        int4            lower;
 
4303
        int4            upper;
 
4304
        bool            reverse;
4293
4305
} generate_subscripts_fctx;
4294
4306
 
4295
4307
/*
4306
4318
        /* stuff done only on the first call of the function */
4307
4319
        if (SRF_IS_FIRSTCALL())
4308
4320
        {
4309
 
                ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
4310
 
                int             reqdim = PG_GETARG_INT32(1);
4311
 
                int    *lb,
4312
 
                           *dimv;
 
4321
                ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
 
4322
                int                     reqdim = PG_GETARG_INT32(1);
 
4323
                int                *lb,
 
4324
                                   *dimv;
4313
4325
 
4314
4326
                /* create a function context for cross-call persistence */
4315
4327
                funcctx = SRF_FIRSTCALL_INIT();
4374
4386
Datum
4375
4387
array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
4376
4388
{
4377
 
        ArrayType       *dims;
4378
 
        ArrayType       *lbs;
4379
 
        ArrayType               *result;
 
4389
        ArrayType  *dims;
 
4390
        ArrayType  *lbs;
 
4391
        ArrayType  *result;
4380
4392
        Oid                     elmtype;
4381
 
        Datum   value;
4382
 
        bool    isnull;
 
4393
        Datum           value;
 
4394
        bool            isnull;
4383
4395
 
4384
4396
        if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
4385
4397
                ereport(ERROR,
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")));
4388
4400
 
4389
4401
        dims = PG_GETARG_ARRAYTYPE_P(1);
4390
 
        lbs  = PG_GETARG_ARRAYTYPE_P(2);
 
4402
        lbs = PG_GETARG_ARRAYTYPE_P(2);
4391
4403
 
4392
4404
        if (!PG_ARGISNULL(0))
4393
4405
        {
4415
4427
Datum
4416
4428
array_fill(PG_FUNCTION_ARGS)
4417
4429
{
4418
 
        ArrayType       *dims;
4419
 
        ArrayType               *result;
 
4430
        ArrayType  *dims;
 
4431
        ArrayType  *result;
4420
4432
        Oid                     elmtype;
4421
 
        Datum   value;
4422
 
        bool    isnull;
 
4433
        Datum           value;
 
4434
        bool            isnull;
4423
4435
 
4424
4436
        if (PG_ARGISNULL(1))
4425
4437
                ereport(ERROR,
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")));
4428
4440
 
4429
4441
        dims = PG_GETARG_ARRAYTYPE_P(1);
4430
4442
 
4451
4463
create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes,
4452
4464
                                          Oid elmtype, int dataoffset)
4453
4465
{
4454
 
        ArrayType *result;
 
4466
        ArrayType  *result;
4455
4467
 
4456
4468
        result = (ArrayType *) palloc0(nbytes);
4457
4469
        SET_VARSIZE(result, nbytes);
4469
4481
                                        Datum value, bool isnull, Oid elmtype,
4470
4482
                                        FunctionCallInfo fcinfo)
4471
4483
{
4472
 
        ArrayType       *result;
4473
 
        int     *dimv;
4474
 
        int     *lbsv;
4475
 
        int     ndims;
4476
 
        int     nitems;
4477
 
        int             deflbs[MAXDIM];
4478
 
        int16 elmlen;
4479
 
        bool elmbyval;
4480
 
        char elmalign;
4481
 
        ArrayMetaState          *my_extra;
 
4484
        ArrayType  *result;
 
4485
        int                *dimv;
 
4486
        int                *lbsv;
 
4487
        int                     ndims;
 
4488
        int                     nitems;
 
4489
        int                     deflbs[MAXDIM];
 
4490
        int16           elmlen;
 
4491
        bool            elmbyval;
 
4492
        char            elmalign;
 
4493
        ArrayMetaState *my_extra;
4482
4494
 
4483
4495
        /*
4484
4496
         * Params checks
4485
4497
         */
4486
4498
        if (ARR_NDIM(dims) != 1)
4487
4499
                ereport(ERROR,
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.")));
4491
4503
 
4492
4504
        if (ARR_LBOUND(dims)[0] != 1)
4493
4505
                ereport(ERROR,
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.")));
4497
4509
 
4498
4510
        if (ARR_HASNULL(dims))
4499
4511
                ereport(ERROR,
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")));
4502
4514
 
4503
4515
        dimv = (int *) ARR_DATA_PTR(dims);
4504
4516
        ndims = ARR_DIMS(dims)[0];
4517
4529
        {
4518
4530
                if (ARR_NDIM(lbs) != 1)
4519
4531
                        ereport(ERROR,
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.")));
4523
4535
 
4524
4536
                if (ARR_LBOUND(lbs)[0] != 1)
4525
4537
                        ereport(ERROR,
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.")));
4529
4541
 
4530
4542
                if (ARR_HASNULL(lbs))
4531
4543
                        ereport(ERROR,
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")));
4534
4546
 
4535
4547
                if (ARR_DIMS(lbs)[0] != ndims)
4536
4548
                        ereport(ERROR,
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.")));
4540
4552
 
4541
4553
                lbsv = (int *) ARR_DATA_PTR(lbs);
4542
4554
        }
4543
4555
        else
4544
4556
        {
4545
 
                int     i;
 
4557
                int                     i;
4546
4558
 
4547
4559
                for (i = 0; i < MAXDIM; i++)
4548
4560
                        deflbs[i] = 1;
4586
4598
        /* compute required space */
4587
4599
        if (!isnull)
4588
4600
        {
4589
 
                int     i;
4590
 
                char            *p;
 
4601
                int                     i;
 
4602
                char       *p;
4591
4603
                int                     nbytes;
4592
4604
                int                     totbytes;
4593
4605
 
4624
4636
        }
4625
4637
        else
4626
4638
        {
4627
 
                int     nbytes;
4628
 
                int     dataoffset;
 
4639
                int                     nbytes;
 
4640
                int                     dataoffset;
4629
4641
 
4630
4642
                dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
4631
4643
                nbytes = dataoffset;
4648
4660
{
4649
4661
        typedef struct
4650
4662
        {
4651
 
                ArrayType *arr;
4652
 
                int             nextelem;
4653
 
                int             numelems;
4654
 
                char   *elemdataptr;    /* this moves with nextelem */
4655
 
                bits8  *arraynullsptr;  /* this does not */
4656
 
                int16   elmlen;
4657
 
                bool    elmbyval;
4658
 
                char    elmalign;
 
4663
                ArrayType  *arr;
 
4664
                int                     nextelem;
 
4665
                int                     numelems;
 
4666
                char       *elemdataptr;        /* this moves with nextelem */
 
4667
                bits8      *arraynullsptr;              /* this does not */
 
4668
                int16           elmlen;
 
4669
                bool            elmbyval;
 
4670
                char            elmalign;
4659
4671
        } array_unnest_fctx;
4660
4672
 
4661
4673
        FuncCallContext *funcctx;
4677
4689
 
4678
4690
                /*
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.)
4684
4696
                 */
4685
4697
                arr = PG_GETARG_ARRAYTYPE_P(0);
4686
4698
 
4710
4722
 
4711
4723
        if (fctx->nextelem < fctx->numelems)
4712
4724
        {
4713
 
                int             offset = fctx->nextelem++;
4714
 
                Datum   elem;
 
4725
                int                     offset = fctx->nextelem++;
 
4726
                Datum           elem;
4715
4727
 
4716
4728
                /*
4717
4729
                 * Check for NULL array element
4727
4739
                        /*
4728
4740
                         * OK, get the element
4729
4741
                         */
4730
 
                        char   *ptr = fctx->elemdataptr;
 
4742
                        char       *ptr = fctx->elemdataptr;
4731
4743
 
4732
4744
                        fcinfo->isnull = false;
4733
4745
                        elem = ArrayCast(ptr, fctx->elmbyval, fctx->elmlen);