8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.96 2005/04/06 16:34:04 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.97 2005/04/10 18:04:20 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -86,12 +86,13 @@ static execution_state *init_execution_state(List *queryTree_list,
86
86
static void init_sql_fcache (FmgrInfo * finfo );
87
87
static void postquel_start (execution_state * es ,SQLFunctionCachePtr fcache );
88
88
static TupleTableSlot * postquel_getnext (execution_state * es );
89
- static void postquel_end (execution_state * es , SQLFunctionCachePtr fcache );
89
+ static void postquel_end (execution_state * es );
90
90
static void postquel_sub_params (SQLFunctionCachePtr fcache ,
91
91
FunctionCallInfo fcinfo );
92
92
static Datum postquel_execute (execution_state * es ,
93
93
FunctionCallInfo fcinfo ,
94
- SQLFunctionCachePtr fcache );
94
+ SQLFunctionCachePtr fcache ,
95
+ MemoryContext resultcontext );
95
96
static void sql_exec_error_callback (void * arg );
96
97
static void ShutdownSQLFunction (Datum arg );
97
98
@@ -384,7 +385,7 @@ postquel_getnext(execution_state *es)
384
385
}
385
386
386
387
static void
387
- postquel_end (execution_state * es , SQLFunctionCachePtr fcache )
388
+ postquel_end (execution_state * es )
388
389
{
389
390
Snapshot saveActiveSnapshot ;
390
391
@@ -454,10 +455,12 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
454
455
static Datum
455
456
postquel_execute (execution_state * es ,
456
457
FunctionCallInfo fcinfo ,
457
- SQLFunctionCachePtr fcache )
458
+ SQLFunctionCachePtr fcache ,
459
+ MemoryContext resultcontext )
458
460
{
459
461
TupleTableSlot * slot ;
460
462
Datum value ;
463
+ MemoryContext oldcontext ;
461
464
462
465
if (es -> status == F_EXEC_START )
463
466
postquel_start (es ,fcache );
@@ -470,7 +473,7 @@ postquel_execute(execution_state *es,
470
473
* We fall out here for all cases except where we have obtained
471
474
* a row from a function's final SELECT.
472
475
*/
473
- postquel_end (es , fcache );
476
+ postquel_end (es );
474
477
fcinfo -> isnull = true;
475
478
return (Datum )NULL ;
476
479
}
@@ -482,8 +485,12 @@ postquel_execute(execution_state *es,
482
485
Assert (LAST_POSTQUEL_COMMAND (es ));
483
486
484
487
/*
485
- * Set up to return the function value.
488
+ * Set up to return the function value. For pass-by-reference
489
+ * datatypes, be sure to allocate the result in resultcontext,
490
+ * not the current memory context (which has query lifespan).
486
491
*/
492
+ oldcontext = MemoryContextSwitchTo (resultcontext );
493
+
487
494
if (fcache -> returnsTuple )
488
495
{
489
496
/*
@@ -492,7 +499,7 @@ postquel_execute(execution_state *es,
492
499
* reasons why we do this:
493
500
*
494
501
* 1. To copy the tuple out of the child execution context and
495
- * intoour own context.
502
+ * intothe desired result context.
496
503
*
497
504
* 2. To remove any junk attributes present in the raw subselect
498
505
* result. (This is probably not absolutely necessary, but it
@@ -553,21 +560,23 @@ postquel_execute(execution_state *es,
553
560
{
554
561
/*
555
562
* Returning a scalar, which we have to extract from the first
556
- * column of the SELECT result, and then copy intocurrent
557
- *execution context if needed.
563
+ * column of the SELECT result, and then copy intoresult
564
+ * context if needed.
558
565
*/
559
566
value = slot_getattr (slot ,1 ,& (fcinfo -> isnull ));
560
567
561
568
if (!fcinfo -> isnull )
562
569
value = datumCopy (value ,fcache -> typbyval ,fcache -> typlen );
563
570
}
564
571
572
+ MemoryContextSwitchTo (oldcontext );
573
+
565
574
/*
566
575
* If this is a single valued function we have to end the function
567
576
* execution now.
568
577
*/
569
578
if (!fcinfo -> flinfo -> fn_retset )
570
- postquel_end (es , fcache );
579
+ postquel_end (es );
571
580
572
581
return value ;
573
582
}
@@ -627,7 +636,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
627
636
*/
628
637
while (es )
629
638
{
630
- result = postquel_execute (es ,fcinfo ,fcache );
639
+ result = postquel_execute (es ,fcinfo ,fcache , oldcontext );
631
640
if (es -> status != F_EXEC_DONE )
632
641
break ;
633
642
es = es -> next ;
@@ -824,7 +833,7 @@ ShutdownSQLFunction(Datum arg)
824
833
{
825
834
/* Shut down anything still running */
826
835
if (es -> status == F_EXEC_RUN )
827
- postquel_end (es , fcache );
836
+ postquel_end (es );
828
837
/* Reset states to START in case we're called again */
829
838
es -> status = F_EXEC_START ;
830
839
es = es -> next ;