~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/pl/plpgsql/src/pl_exec.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-01-03 08:57:10 UTC
  • mfrom: (5.3.10 sid)
  • Revision ID: james.westby@ubuntu.com-20110103085710-v9u121v7u7oq8qca
Tags: 8.4.6-1~hardy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 *
9
9
 *
10
10
 * IDENTIFICATION
11
 
 *        $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.244.2.4 2010/04/14 23:52:16 tgl Exp $
 
11
 *        $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.244.2.10 2010/08/19 18:11:02 tgl Exp $
12
12
 *
13
13
 *-------------------------------------------------------------------------
14
14
 */
1076
1076
                         */
1077
1077
                        SPI_restore_connection();
1078
1078
 
 
1079
                        /* Must clean up the econtext too */
 
1080
                        exec_eval_cleanup(estate);
 
1081
 
1079
1082
                        /* Look for a matching exception handler */
1080
1083
                        foreach(e, block->exceptions->exc_list)
1081
1084
                        {
2636
2639
 *
2637
2640
 * NB: the result of the evaluation is no longer valid after this is done,
2638
2641
 * unless it is a pass-by-value datatype.
 
2642
 *
 
2643
 * NB: if you change this code, see also the hacks in exec_assign_value's
 
2644
 * PLPGSQL_DTYPE_ARRAYELEM case.
2639
2645
 * ----------
2640
2646
 */
2641
2647
static void
3443
3449
 
3444
3450
/* ----------
3445
3451
 * exec_assign_value                    Put a value into a target field
 
3452
 *
 
3453
 * Note: in some code paths, this may leak memory in the eval_econtext;
 
3454
 * we assume that will be cleaned up later by exec_eval_cleanup.  We cannot
 
3455
 * call exec_eval_cleanup here for fear of destroying the input Datum value.
3446
3456
 * ----------
3447
3457
 */
3448
3458
static void
3693
3703
 
3694
3704
                case PLPGSQL_DTYPE_ARRAYELEM:
3695
3705
                        {
 
3706
                                /*
 
3707
                                 * Target is an element of an array
 
3708
                                 */
3696
3709
                                int                     nsubscripts;
3697
3710
                                int                     i;
3698
3711
                                PLpgSQL_expr *subscripts[MAXDIM];
3708
3721
                                                        coerced_value;
3709
3722
                                ArrayType  *oldarrayval;
3710
3723
                                ArrayType  *newarrayval;
3711
 
 
3712
 
                                /*
3713
 
                                 * Target is an element of an array
3714
 
                                 *
 
3724
                                SPITupleTable *save_eval_tuptable;
 
3725
 
 
3726
                                /*
 
3727
                                 * We need to do subscript evaluation, which might require
 
3728
                                 * evaluating general expressions; and the caller might have
 
3729
                                 * done that too in order to prepare the input Datum.  We
 
3730
                                 * have to save and restore the caller's SPI_execute result,
 
3731
                                 * if any.
 
3732
                                 */
 
3733
                                save_eval_tuptable = estate->eval_tuptable;
 
3734
                                estate->eval_tuptable = NULL;
 
3735
 
 
3736
                                /*
3715
3737
                                 * To handle constructs like x[1][2] := something, we have to
3716
3738
                                 * be prepared to deal with a chain of arrayelem datums. Chase
3717
3739
                                 * back to find the base array datum, and save the subscript
3765
3787
                                                ereport(ERROR,
3766
3788
                                                                (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3767
3789
                                                                 errmsg("array subscript in assignment must not be null")));
 
3790
 
 
3791
                                        /*
 
3792
                                         * Clean up in case the subscript expression wasn't simple.
 
3793
                                         * We can't do exec_eval_cleanup, but we can do this much
 
3794
                                         * (which is safe because the integer subscript value is
 
3795
                                         * surely pass-by-value), and we must do it in case the
 
3796
                                         * next subscript expression isn't simple either.
 
3797
                                         */
 
3798
                                        if (estate->eval_tuptable != NULL)
 
3799
                                                SPI_freetuptable(estate->eval_tuptable);
 
3800
                                        estate->eval_tuptable = NULL;
3768
3801
                                }
3769
3802
 
 
3803
                                /* Now we can restore caller's SPI_execute result if any. */
 
3804
                                Assert(estate->eval_tuptable == NULL);
 
3805
                                estate->eval_tuptable = save_eval_tuptable;
 
3806
 
3770
3807
                                /* Coerce source value to match array element type. */
3771
3808
                                coerced_value = exec_simple_cast_value(value,
3772
3809
                                                                                                           valtype,
4212
4249
                elog(ERROR, "unsupported target");
4213
4250
 
4214
4251
        /*
 
4252
         * Make sure the portal doesn't get closed by the user statements
 
4253
         * we execute.
 
4254
         */
 
4255
        PinPortal(portal);
 
4256
 
 
4257
        /*
4215
4258
         * Fetch the initial tuple(s).  If prefetching is allowed then we grab a
4216
4259
         * few more rows to avoid multiple trips through executor startup
4217
4260
         * overhead.
4321
4364
         */
4322
4365
        SPI_freetuptable(tuptab);
4323
4366
 
 
4367
        UnpinPortal(portal);
 
4368
 
4324
4369
        /*
4325
4370
         * Set the FOUND variable to indicate the result of executing the loop
4326
4371
         * (namely, whether we looped one or more times). This must be set last so
4338
4383
 *                                                              a Datum by directly calling ExecEvalExpr().
4339
4384
 *
4340
4385
 * If successful, store results into *result, *isNull, *rettype and return
4341
 
 * TRUE.  If the expression is not simple (any more), return FALSE.
 
4386
 * TRUE.  If the expression cannot be handled by simple evaluation,
 
4387
 * return FALSE.
 
4388
 *
 
4389
 * Because we only store one execution tree for a simple expression, we
 
4390
 * can't handle recursion cases.  So, if we see the tree is already busy
 
4391
 * with an evaluation in the current xact, we just return FALSE and let the
 
4392
 * caller run the expression the hard way.  (Other alternatives such as
 
4393
 * creating a new tree for a recursive call either introduce memory leaks,
 
4394
 * or add enough bookkeeping to be doubtful wins anyway.)  Another case that
 
4395
 * is covered by the expr_simple_in_use test is where a previous execution
 
4396
 * of the tree was aborted by an error: the tree may contain bogus state
 
4397
 * so we dare not re-use it.
4342
4398
 *
4343
4399
 * It is possible though unlikely for a simple expression to become non-simple
4344
4400
 * (consider for example redefining a trivial view).  We must handle that for
4375
4431
                return false;
4376
4432
 
4377
4433
        /*
 
4434
         * If expression is in use in current xact, don't touch it.
 
4435
         */
 
4436
        if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
 
4437
                return false;
 
4438
 
 
4439
        /*
4378
4440
         * Revalidate cached plan, so that we will notice if it became stale. (We
4379
4441
         * also need to hold a refcount while using the plan.)  Note that even if
4380
4442
         * replanning occurs, the length of plancache_list can't change, since it
4409
4471
        {
4410
4472
                expr->expr_simple_state = ExecPrepareExpr(expr->expr_simple_expr,
4411
4473
                                                                                                  simple_eval_estate);
 
4474
                expr->expr_simple_in_use = false;
4412
4475
                expr->expr_simple_lxid = curlxid;
4413
4476
        }
4414
4477
 
4464
4527
        }
4465
4528
 
4466
4529
        /*
 
4530
         * Mark expression as busy for the duration of the ExecEvalExpr call.
 
4531
         */
 
4532
        expr->expr_simple_in_use = true;
 
4533
 
 
4534
        /*
4467
4535
         * Finally we can call the executor to evaluate the expression
4468
4536
         */
4469
4537
        *result = ExecEvalExpr(expr->expr_simple_state,
4470
4538
                                                   econtext,
4471
4539
                                                   isNull,
4472
4540
                                                   NULL);
 
4541
 
 
4542
        /* Assorted cleanup */
 
4543
        expr->expr_simple_in_use = false;
 
4544
 
4473
4545
        MemoryContextSwitchTo(oldcontext);
4474
4546
 
4475
4547
        if (!estate->readonly_func)
5103
5175
         */
5104
5176
        if (!IsA(stmt, PlannedStmt))
5105
5177
                return;
 
5178
        if (stmt->commandType != CMD_SELECT || stmt->intoClause)
 
5179
                return;
5106
5180
        plan = stmt->planTree;
5107
5181
        if (!IsA(plan, Result))
5108
5182
                return;
5137
5211
         */
5138
5212
        expr->expr_simple_expr = tle->expr;
5139
5213
        expr->expr_simple_state = NULL;
 
5214
        expr->expr_simple_in_use = false;
5140
5215
        expr->expr_simple_lxid = InvalidLocalTransactionId;
5141
5216
        /* Also stash away the expression result type */
5142
5217
        expr->expr_simple_type = exprType((Node *) tle->expr);
5383
5458
                ppd->nulls[i] = isnull ? 'n' : ' ';
5384
5459
                ppd->freevals[i] = false;
5385
5460
 
 
5461
                if (ppd->types[i] == UNKNOWNOID)
 
5462
                {
 
5463
                        /*
 
5464
                         * Treat 'unknown' parameters as text, since that's what most
 
5465
                         * people would expect. SPI_execute_with_args can coerce unknown
 
5466
                         * constants in a more intelligent way, but not unknown Params.
 
5467
                         * This code also takes care of copying into the right context.
 
5468
                         * Note we assume 'unknown' has the representation of C-string.
 
5469
                         */
 
5470
                        ppd->types[i] = TEXTOID;
 
5471
                        if (!isnull)
 
5472
                        {
 
5473
                                ppd->values[i] = CStringGetTextDatum(DatumGetCString(ppd->values[i]));
 
5474
                                ppd->freevals[i] = true;
 
5475
                        }
 
5476
                }
5386
5477
                /* pass-by-ref non null values must be copied into plpgsql context */
5387
 
                if (!isnull)
 
5478
                else if (!isnull)
5388
5479
                {
5389
5480
                        int16           typLen;
5390
5481
                        bool            typByVal;