LCOV - code coverage report
Current view: top level - src/pl/plpgsql/src - pl_exec.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 1962 2242 87.5 %
Date: 2017-09-29 15:12:54 Functions: 77 77 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pl_exec.c        - Executor for the PL/pgSQL
       4             :  *            procedural language
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/pl/plpgsql/src/pl_exec.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include <ctype.h>
      19             : 
      20             : #include "access/htup_details.h"
      21             : #include "access/transam.h"
      22             : #include "access/tupconvert.h"
      23             : #include "catalog/pg_proc.h"
      24             : #include "catalog/pg_type.h"
      25             : #include "executor/spi.h"
      26             : #include "funcapi.h"
      27             : #include "miscadmin.h"
      28             : #include "nodes/nodeFuncs.h"
      29             : #include "optimizer/planner.h"
      30             : #include "parser/parse_coerce.h"
      31             : #include "parser/scansup.h"
      32             : #include "storage/proc.h"
      33             : #include "tcop/tcopprot.h"
      34             : #include "utils/array.h"
      35             : #include "utils/builtins.h"
      36             : #include "utils/datum.h"
      37             : #include "utils/fmgroids.h"
      38             : #include "utils/lsyscache.h"
      39             : #include "utils/memutils.h"
      40             : #include "utils/rel.h"
      41             : #include "utils/snapmgr.h"
      42             : #include "utils/typcache.h"
      43             : 
      44             : #include "plpgsql.h"
      45             : 
      46             : 
      47             : typedef struct
      48             : {
      49             :     int         nargs;          /* number of arguments */
      50             :     Oid        *types;          /* types of arguments */
      51             :     Datum      *values;         /* evaluated argument values */
      52             :     char       *nulls;          /* null markers (' '/'n' style) */
      53             : } PreparedParamsData;
      54             : 
      55             : /*
      56             :  * All plpgsql function executions within a single transaction share the same
      57             :  * executor EState for evaluating "simple" expressions.  Each function call
      58             :  * creates its own "eval_econtext" ExprContext within this estate for
      59             :  * per-evaluation workspace.  eval_econtext is freed at normal function exit,
      60             :  * and the EState is freed at transaction end (in case of error, we assume
      61             :  * that the abort mechanisms clean it all up).  Furthermore, any exception
      62             :  * block within a function has to have its own eval_econtext separate from
      63             :  * the containing function's, so that we can clean up ExprContext callbacks
      64             :  * properly at subtransaction exit.  We maintain a stack that tracks the
      65             :  * individual econtexts so that we can clean up correctly at subxact exit.
      66             :  *
      67             :  * This arrangement is a bit tedious to maintain, but it's worth the trouble
      68             :  * so that we don't have to re-prepare simple expressions on each trip through
      69             :  * a function.  (We assume the case to optimize is many repetitions of a
      70             :  * function within a transaction.)
      71             :  *
      72             :  * However, there's no value in trying to amortize simple expression setup
      73             :  * across multiple executions of a DO block (inline code block), since there
      74             :  * can never be any.  If we use the shared EState for a DO block, the expr
      75             :  * state trees are effectively leaked till end of transaction, and that can
      76             :  * add up if the user keeps on submitting DO blocks.  Therefore, each DO block
      77             :  * has its own simple-expression EState, which is cleaned up at exit from
      78             :  * plpgsql_inline_handler().  DO blocks still use the simple_econtext_stack,
      79             :  * though, so that subxact abort cleanup does the right thing.
      80             :  */
      81             : typedef struct SimpleEcontextStackEntry
      82             : {
      83             :     ExprContext *stack_econtext;    /* a stacked econtext */
      84             :     SubTransactionId xact_subxid;   /* ID for current subxact */
      85             :     struct SimpleEcontextStackEntry *next;  /* next stack entry up */
      86             : } SimpleEcontextStackEntry;
      87             : 
      88             : static EState *shared_simple_eval_estate = NULL;
      89             : static SimpleEcontextStackEntry *simple_econtext_stack = NULL;
      90             : 
      91             : /*
      92             :  * Memory management within a plpgsql function generally works with three
      93             :  * contexts:
      94             :  *
      95             :  * 1. Function-call-lifespan data, such as variable values, is kept in the
      96             :  * "main" context, a/k/a the "SPI Proc" context established by SPI_connect().
      97             :  * This is usually the CurrentMemoryContext while running code in this module
      98             :  * (which is not good, because careless coding can easily cause
      99             :  * function-lifespan memory leaks, but we live with it for now).
     100             :  *
     101             :  * 2. Some statement-execution routines need statement-lifespan workspace.
     102             :  * A suitable context is created on-demand by get_stmt_mcontext(), and must
     103             :  * be reset at the end of the requesting routine.  Error recovery will clean
     104             :  * it up automatically.  Nested statements requiring statement-lifespan
     105             :  * workspace will result in a stack of such contexts, see push_stmt_mcontext().
     106             :  *
     107             :  * 3. We use the eval_econtext's per-tuple memory context for expression
     108             :  * evaluation, and as a general-purpose workspace for short-lived allocations.
     109             :  * Such allocations usually aren't explicitly freed, but are left to be
     110             :  * cleaned up by a context reset, typically done by exec_eval_cleanup().
     111             :  *
     112             :  * These macros are for use in making short-lived allocations:
     113             :  */
     114             : #define get_eval_mcontext(estate) \
     115             :     ((estate)->eval_econtext->ecxt_per_tuple_memory)
     116             : #define eval_mcontext_alloc(estate, sz) \
     117             :     MemoryContextAlloc(get_eval_mcontext(estate), sz)
     118             : #define eval_mcontext_alloc0(estate, sz) \
     119             :     MemoryContextAllocZero(get_eval_mcontext(estate), sz)
     120             : 
     121             : /*
     122             :  * We use a session-wide hash table for caching cast information.
     123             :  *
     124             :  * Once built, the compiled expression trees (cast_expr fields) survive for
     125             :  * the life of the session.  At some point it might be worth invalidating
     126             :  * those after pg_cast changes, but for the moment we don't bother.
     127             :  *
     128             :  * The evaluation state trees (cast_exprstate) are managed in the same way as
     129             :  * simple expressions (i.e., we assume cast expressions are always simple).
     130             :  *
     131             :  * As with simple expressions, DO blocks don't use the shared hash table but
     132             :  * must have their own.  This isn't ideal, but we don't want to deal with
     133             :  * multiple simple_eval_estates within a DO block.
     134             :  */
     135             : typedef struct                  /* lookup key for cast info */
     136             : {
     137             :     /* NB: we assume this struct contains no padding bytes */
     138             :     Oid         srctype;        /* source type for cast */
     139             :     Oid         dsttype;        /* destination type for cast */
     140             :     int32       srctypmod;      /* source typmod for cast */
     141             :     int32       dsttypmod;      /* destination typmod for cast */
     142             : } plpgsql_CastHashKey;
     143             : 
     144             : typedef struct                  /* cast_hash table entry */
     145             : {
     146             :     plpgsql_CastHashKey key;    /* hash key --- MUST BE FIRST */
     147             :     Expr       *cast_expr;      /* cast expression, or NULL if no-op cast */
     148             :     /* ExprState is valid only when cast_lxid matches current LXID */
     149             :     ExprState  *cast_exprstate; /* expression's eval tree */
     150             :     bool        cast_in_use;    /* true while we're executing eval tree */
     151             :     LocalTransactionId cast_lxid;
     152             : } plpgsql_CastHashEntry;
     153             : 
     154             : static MemoryContext shared_cast_context = NULL;
     155             : static HTAB *shared_cast_hash = NULL;
     156             : 
     157             : /************************************************************
     158             :  * Local function forward declarations
     159             :  ************************************************************/
     160             : static void plpgsql_exec_error_callback(void *arg);
     161             : static PLpgSQL_datum *copy_plpgsql_datum(PLpgSQL_datum *datum);
     162             : static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate);
     163             : static void push_stmt_mcontext(PLpgSQL_execstate *estate);
     164             : static void pop_stmt_mcontext(PLpgSQL_execstate *estate);
     165             : 
     166             : static int exec_stmt_block(PLpgSQL_execstate *estate,
     167             :                 PLpgSQL_stmt_block *block);
     168             : static int exec_stmts(PLpgSQL_execstate *estate,
     169             :            List *stmts);
     170             : static int exec_stmt(PLpgSQL_execstate *estate,
     171             :           PLpgSQL_stmt *stmt);
     172             : static int exec_stmt_assign(PLpgSQL_execstate *estate,
     173             :                  PLpgSQL_stmt_assign *stmt);
     174             : static int exec_stmt_perform(PLpgSQL_execstate *estate,
     175             :                   PLpgSQL_stmt_perform *stmt);
     176             : static int exec_stmt_getdiag(PLpgSQL_execstate *estate,
     177             :                   PLpgSQL_stmt_getdiag *stmt);
     178             : static int exec_stmt_if(PLpgSQL_execstate *estate,
     179             :              PLpgSQL_stmt_if *stmt);
     180             : static int exec_stmt_case(PLpgSQL_execstate *estate,
     181             :                PLpgSQL_stmt_case *stmt);
     182             : static int exec_stmt_loop(PLpgSQL_execstate *estate,
     183             :                PLpgSQL_stmt_loop *stmt);
     184             : static int exec_stmt_while(PLpgSQL_execstate *estate,
     185             :                 PLpgSQL_stmt_while *stmt);
     186             : static int exec_stmt_fori(PLpgSQL_execstate *estate,
     187             :                PLpgSQL_stmt_fori *stmt);
     188             : static int exec_stmt_fors(PLpgSQL_execstate *estate,
     189             :                PLpgSQL_stmt_fors *stmt);
     190             : static int exec_stmt_forc(PLpgSQL_execstate *estate,
     191             :                PLpgSQL_stmt_forc *stmt);
     192             : static int exec_stmt_foreach_a(PLpgSQL_execstate *estate,
     193             :                     PLpgSQL_stmt_foreach_a *stmt);
     194             : static int exec_stmt_open(PLpgSQL_execstate *estate,
     195             :                PLpgSQL_stmt_open *stmt);
     196             : static int exec_stmt_fetch(PLpgSQL_execstate *estate,
     197             :                 PLpgSQL_stmt_fetch *stmt);
     198             : static int exec_stmt_close(PLpgSQL_execstate *estate,
     199             :                 PLpgSQL_stmt_close *stmt);
     200             : static int exec_stmt_exit(PLpgSQL_execstate *estate,
     201             :                PLpgSQL_stmt_exit *stmt);
     202             : static int exec_stmt_return(PLpgSQL_execstate *estate,
     203             :                  PLpgSQL_stmt_return *stmt);
     204             : static int exec_stmt_return_next(PLpgSQL_execstate *estate,
     205             :                       PLpgSQL_stmt_return_next *stmt);
     206             : static int exec_stmt_return_query(PLpgSQL_execstate *estate,
     207             :                        PLpgSQL_stmt_return_query *stmt);
     208             : static int exec_stmt_raise(PLpgSQL_execstate *estate,
     209             :                 PLpgSQL_stmt_raise *stmt);
     210             : static int exec_stmt_assert(PLpgSQL_execstate *estate,
     211             :                  PLpgSQL_stmt_assert *stmt);
     212             : static int exec_stmt_execsql(PLpgSQL_execstate *estate,
     213             :                   PLpgSQL_stmt_execsql *stmt);
     214             : static int exec_stmt_dynexecute(PLpgSQL_execstate *estate,
     215             :                      PLpgSQL_stmt_dynexecute *stmt);
     216             : static int exec_stmt_dynfors(PLpgSQL_execstate *estate,
     217             :                   PLpgSQL_stmt_dynfors *stmt);
     218             : 
     219             : static void plpgsql_estate_setup(PLpgSQL_execstate *estate,
     220             :                      PLpgSQL_function *func,
     221             :                      ReturnSetInfo *rsi,
     222             :                      EState *simple_eval_estate);
     223             : static void exec_eval_cleanup(PLpgSQL_execstate *estate);
     224             : 
     225             : static void exec_prepare_plan(PLpgSQL_execstate *estate,
     226             :                   PLpgSQL_expr *expr, int cursorOptions);
     227             : static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr);
     228             : static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan);
     229             : static void exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno);
     230             : static bool contains_target_param(Node *node, int *target_dno);
     231             : static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,
     232             :                       PLpgSQL_expr *expr,
     233             :                       Datum *result,
     234             :                       bool *isNull,
     235             :                       Oid *rettype,
     236             :                       int32 *rettypmod);
     237             : 
     238             : static void exec_assign_expr(PLpgSQL_execstate *estate,
     239             :                  PLpgSQL_datum *target,
     240             :                  PLpgSQL_expr *expr);
     241             : static void exec_assign_c_string(PLpgSQL_execstate *estate,
     242             :                      PLpgSQL_datum *target,
     243             :                      const char *str);
     244             : static void exec_assign_value(PLpgSQL_execstate *estate,
     245             :                   PLpgSQL_datum *target,
     246             :                   Datum value, bool isNull,
     247             :                   Oid valtype, int32 valtypmod);
     248             : static void exec_eval_datum(PLpgSQL_execstate *estate,
     249             :                 PLpgSQL_datum *datum,
     250             :                 Oid *typeid,
     251             :                 int32 *typetypmod,
     252             :                 Datum *value,
     253             :                 bool *isnull);
     254             : static int exec_eval_integer(PLpgSQL_execstate *estate,
     255             :                   PLpgSQL_expr *expr,
     256             :                   bool *isNull);
     257             : static bool exec_eval_boolean(PLpgSQL_execstate *estate,
     258             :                   PLpgSQL_expr *expr,
     259             :                   bool *isNull);
     260             : static Datum exec_eval_expr(PLpgSQL_execstate *estate,
     261             :                PLpgSQL_expr *expr,
     262             :                bool *isNull,
     263             :                Oid *rettype,
     264             :                int32 *rettypmod);
     265             : static int exec_run_select(PLpgSQL_execstate *estate,
     266             :                 PLpgSQL_expr *expr, long maxtuples, Portal *portalP);
     267             : static int exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
     268             :                Portal portal, bool prefetch_ok);
     269             : static ParamListInfo setup_param_list(PLpgSQL_execstate *estate,
     270             :                  PLpgSQL_expr *expr);
     271             : static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate,
     272             :                           PLpgSQL_expr *expr);
     273             : static void plpgsql_param_fetch(ParamListInfo params, int paramid);
     274             : static void exec_move_row(PLpgSQL_execstate *estate,
     275             :               PLpgSQL_rec *rec,
     276             :               PLpgSQL_row *row,
     277             :               HeapTuple tup, TupleDesc tupdesc);
     278             : static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
     279             :                     PLpgSQL_row *row,
     280             :                     TupleDesc tupdesc);
     281             : static HeapTuple get_tuple_from_datum(Datum value);
     282             : static TupleDesc get_tupdesc_from_datum(Datum value);
     283             : static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
     284             :                          PLpgSQL_rec *rec,
     285             :                          PLpgSQL_row *row,
     286             :                          Datum value);
     287             : static char *convert_value_to_string(PLpgSQL_execstate *estate,
     288             :                         Datum value, Oid valtype);
     289             : static Datum exec_cast_value(PLpgSQL_execstate *estate,
     290             :                 Datum value, bool *isnull,
     291             :                 Oid valtype, int32 valtypmod,
     292             :                 Oid reqtype, int32 reqtypmod);
     293             : static plpgsql_CastHashEntry *get_cast_hashentry(PLpgSQL_execstate *estate,
     294             :                    Oid srctype, int32 srctypmod,
     295             :                    Oid dsttype, int32 dsttypmod);
     296             : static void exec_init_tuple_store(PLpgSQL_execstate *estate);
     297             : static void exec_set_found(PLpgSQL_execstate *estate, bool state);
     298             : static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
     299             : static void plpgsql_destroy_econtext(PLpgSQL_execstate *estate);
     300             : static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
     301             :                   Datum newvalue, bool isnull, bool freeable);
     302             : static void assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
     303             :                 const char *str);
     304             : static PreparedParamsData *exec_eval_using_params(PLpgSQL_execstate *estate,
     305             :                        List *params);
     306             : static Portal exec_dynquery_with_params(PLpgSQL_execstate *estate,
     307             :                           PLpgSQL_expr *dynquery, List *params,
     308             :                           const char *portalname, int cursorOptions);
     309             : static char *format_expr_params(PLpgSQL_execstate *estate,
     310             :                    const PLpgSQL_expr *expr);
     311             : static char *format_preparedparamsdata(PLpgSQL_execstate *estate,
     312             :                           const PreparedParamsData *ppd);
     313             : 
     314             : 
     315             : /* ----------
     316             :  * plpgsql_exec_function    Called by the call handler for
     317             :  *              function execution.
     318             :  *
     319             :  * This is also used to execute inline code blocks (DO blocks).  The only
     320             :  * difference that this code is aware of is that for a DO block, we want
     321             :  * to use a private simple_eval_estate, which is created and passed in by
     322             :  * the caller.  For regular functions, pass NULL, which implies using
     323             :  * shared_simple_eval_estate.  (When using a private simple_eval_estate,
     324             :  * we must also use a private cast hashtable, but that's taken care of
     325             :  * within plpgsql_estate_setup.)
     326             :  * ----------
     327             :  */
     328             : Datum
     329       10450 : plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
     330             :                       EState *simple_eval_estate)
     331             : {
     332             :     PLpgSQL_execstate estate;
     333             :     ErrorContextCallback plerrcontext;
     334             :     int         i;
     335             :     int         rc;
     336             : 
     337             :     /*
     338             :      * Setup the execution state
     339             :      */
     340       10450 :     plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
     341             :                          simple_eval_estate);
     342             : 
     343             :     /*
     344             :      * Setup error traceback support for ereport()
     345             :      */
     346       10450 :     plerrcontext.callback = plpgsql_exec_error_callback;
     347       10450 :     plerrcontext.arg = &estate;
     348       10450 :     plerrcontext.previous = error_context_stack;
     349       10450 :     error_context_stack = &plerrcontext;
     350             : 
     351             :     /*
     352             :      * Make local execution copies of all the datums
     353             :      */
     354       10450 :     estate.err_text = gettext_noop("during initialization of execution state");
     355       39990 :     for (i = 0; i < estate.ndatums; i++)
     356       29540 :         estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
     357             : 
     358             :     /*
     359             :      * Store the actual call argument values into the appropriate variables
     360             :      */
     361       10450 :     estate.err_text = gettext_noop("while storing call arguments into local variables");
     362       26268 :     for (i = 0; i < func->fn_nargs; i++)
     363             :     {
     364       15818 :         int         n = func->fn_argvarnos[i];
     365             : 
     366       15818 :         switch (estate.datums[n]->dtype)
     367             :         {
     368             :             case PLPGSQL_DTYPE_VAR:
     369             :                 {
     370       15777 :                     PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
     371             : 
     372       15777 :                     assign_simple_var(&estate, var,
     373             :                                       fcinfo->arg[i],
     374       15777 :                                       fcinfo->argnull[i],
     375             :                                       false);
     376             : 
     377             :                     /*
     378             :                      * Force any array-valued parameter to be stored in
     379             :                      * expanded form in our local variable, in hopes of
     380             :                      * improving efficiency of uses of the variable.  (This is
     381             :                      * a hack, really: why only arrays? Need more thought
     382             :                      * about which cases are likely to win.  See also
     383             :                      * typisarray-specific heuristic in exec_assign_value.)
     384             :                      *
     385             :                      * Special cases: If passed a R/W expanded pointer, assume
     386             :                      * we can commandeer the object rather than having to copy
     387             :                      * it.  If passed a R/O expanded pointer, just keep it as
     388             :                      * the value of the variable for the moment.  (We'll force
     389             :                      * it to R/W if the variable gets modified, but that may
     390             :                      * very well never happen.)
     391             :                      */
     392       15777 :                     if (!var->isnull && var->datatype->typisarray)
     393             :                     {
     394          40 :                         if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value)))
     395             :                         {
     396             :                             /* take ownership of R/W object */
     397           0 :                             assign_simple_var(&estate, var,
     398             :                                               TransferExpandedObject(var->value,
     399             :                                                                      CurrentMemoryContext),
     400             :                                               false,
     401             :                                               true);
     402             :                         }
     403          40 :                         else if (VARATT_IS_EXTERNAL_EXPANDED_RO(DatumGetPointer(var->value)))
     404             :                         {
     405             :                             /* R/O pointer, keep it as-is until assigned to */
     406             :                         }
     407             :                         else
     408             :                         {
     409             :                             /* flat array, so force to expanded form */
     410          32 :                             assign_simple_var(&estate, var,
     411             :                                               expand_array(var->value,
     412             :                                                            CurrentMemoryContext,
     413             :                                                            NULL),
     414             :                                               false,
     415             :                                               true);
     416             :                         }
     417             :                     }
     418             :                 }
     419       15777 :                 break;
     420             : 
     421             :             case PLPGSQL_DTYPE_ROW:
     422             :                 {
     423          41 :                     PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
     424             : 
     425          41 :                     if (!fcinfo->argnull[i])
     426             :                     {
     427             :                         /* Assign row value from composite datum */
     428          32 :                         exec_move_row_from_datum(&estate, NULL, row,
     429             :                                                  fcinfo->arg[i]);
     430             :                     }
     431             :                     else
     432             :                     {
     433             :                         /* If arg is null, treat it as an empty row */
     434           9 :                         exec_move_row(&estate, NULL, row, NULL, NULL);
     435             :                     }
     436             :                     /* clean up after exec_move_row() */
     437          41 :                     exec_eval_cleanup(&estate);
     438             :                 }
     439          41 :                 break;
     440             : 
     441             :             default:
     442           0 :                 elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
     443             :         }
     444             :     }
     445             : 
     446       10450 :     estate.err_text = gettext_noop("during function entry");
     447             : 
     448             :     /*
     449             :      * Set the magic variable FOUND to false
     450             :      */
     451       10450 :     exec_set_found(&estate, false);
     452             : 
     453             :     /*
     454             :      * Let the instrumentation plugin peek at this function
     455             :      */
     456       10450 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
     457           0 :         ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
     458             : 
     459             :     /*
     460             :      * Now call the toplevel block of statements
     461             :      */
     462       10450 :     estate.err_text = NULL;
     463       10450 :     estate.err_stmt = (PLpgSQL_stmt *) (func->action);
     464       10450 :     rc = exec_stmt_block(&estate, func->action);
     465       10364 :     if (rc != PLPGSQL_RC_RETURN)
     466             :     {
     467           1 :         estate.err_stmt = NULL;
     468           1 :         estate.err_text = NULL;
     469           1 :         ereport(ERROR,
     470             :                 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
     471             :                  errmsg("control reached end of function without RETURN")));
     472             :     }
     473             : 
     474             :     /*
     475             :      * We got a return value - process it
     476             :      */
     477       10363 :     estate.err_stmt = NULL;
     478       10363 :     estate.err_text = gettext_noop("while casting return value to function's return type");
     479             : 
     480       10363 :     fcinfo->isnull = estate.retisnull;
     481             : 
     482       10363 :     if (estate.retisset)
     483             :     {
     484          77 :         ReturnSetInfo *rsi = estate.rsi;
     485             : 
     486             :         /* Check caller can handle a set result */
     487         154 :         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
     488          77 :             (rsi->allowedModes & SFRM_Materialize) == 0)
     489           0 :             ereport(ERROR,
     490             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     491             :                      errmsg("set-valued function called in context that cannot accept a set")));
     492          77 :         rsi->returnMode = SFRM_Materialize;
     493             : 
     494             :         /* If we produced any tuples, send back the result */
     495          77 :         if (estate.tuple_store)
     496             :         {
     497          74 :             rsi->setResult = estate.tuple_store;
     498          74 :             if (estate.rettupdesc)
     499             :             {
     500             :                 MemoryContext oldcxt;
     501             : 
     502          74 :                 oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
     503          74 :                 rsi->setDesc = CreateTupleDescCopy(estate.rettupdesc);
     504          74 :                 MemoryContextSwitchTo(oldcxt);
     505             :             }
     506             :         }
     507          77 :         estate.retval = (Datum) 0;
     508          77 :         fcinfo->isnull = true;
     509             :     }
     510       10286 :     else if (!estate.retisnull)
     511             :     {
     512       10282 :         if (estate.retistuple)
     513             :         {
     514             :             /*
     515             :              * We have to check that the returned tuple actually matches the
     516             :              * expected result type.  XXX would be better to cache the tupdesc
     517             :              * instead of repeating get_call_result_type()
     518             :              */
     519          51 :             HeapTuple   rettup = (HeapTuple) DatumGetPointer(estate.retval);
     520             :             TupleDesc   tupdesc;
     521             :             TupleConversionMap *tupmap;
     522             : 
     523          51 :             switch (get_call_result_type(fcinfo, NULL, &tupdesc))
     524             :             {
     525             :                 case TYPEFUNC_COMPOSITE:
     526             :                     /* got the expected result rowtype, now check it */
     527          43 :                     tupmap = convert_tuples_by_position(estate.rettupdesc,
     528             :                                                         tupdesc,
     529             :                                                         gettext_noop("returned record type does not match expected record type"));
     530             :                     /* it might need conversion */
     531          42 :                     if (tupmap)
     532           0 :                         rettup = do_convert_tuple(rettup, tupmap);
     533             :                     /* no need to free map, we're about to return anyway */
     534          42 :                     break;
     535             :                 case TYPEFUNC_RECORD:
     536             : 
     537             :                     /*
     538             :                      * Failed to determine actual type of RECORD.  We could
     539             :                      * raise an error here, but what this means in practice is
     540             :                      * that the caller is expecting any old generic rowtype,
     541             :                      * so we don't really need to be restrictive. Pass back
     542             :                      * the generated result type, instead.
     543             :                      */
     544           8 :                     tupdesc = estate.rettupdesc;
     545           8 :                     if (tupdesc == NULL)    /* shouldn't happen */
     546           0 :                         elog(ERROR, "return type must be a row type");
     547           8 :                     break;
     548             :                 default:
     549             :                     /* shouldn't get here if retistuple is true ... */
     550           0 :                     elog(ERROR, "return type must be a row type");
     551             :                     break;
     552             :             }
     553             : 
     554             :             /*
     555             :              * Copy tuple to upper executor memory, as a tuple Datum. Make
     556             :              * sure it is labeled with the caller-supplied tuple type.
     557             :              */
     558          50 :             estate.retval = PointerGetDatum(SPI_returntuple(rettup, tupdesc));
     559             :         }
     560             :         else
     561             :         {
     562             :             /* Cast value to proper type */
     563       10231 :             estate.retval = exec_cast_value(&estate,
     564             :                                             estate.retval,
     565             :                                             &fcinfo->isnull,
     566             :                                             estate.rettype,
     567             :                                             -1,
     568             :                                             func->fn_rettype,
     569             :                                             -1);
     570             : 
     571             :             /*
     572             :              * If the function's return type isn't by value, copy the value
     573             :              * into upper executor memory context.  However, if we have a R/W
     574             :              * expanded datum, we can just transfer its ownership out to the
     575             :              * upper executor context.
     576             :              */
     577       10227 :             if (!fcinfo->isnull && !func->fn_retbyval)
     578         162 :                 estate.retval = SPI_datumTransfer(estate.retval,
     579             :                                                   false,
     580             :                                                   func->fn_rettyplen);
     581             :         }
     582             :     }
     583             : 
     584       10358 :     estate.err_text = gettext_noop("during function exit");
     585             : 
     586             :     /*
     587             :      * Let the instrumentation plugin peek at this function
     588             :      */
     589       10358 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
     590           0 :         ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
     591             : 
     592             :     /* Clean up any leftover temporary memory */
     593       10358 :     plpgsql_destroy_econtext(&estate);
     594       10358 :     exec_eval_cleanup(&estate);
     595             :     /* stmt_mcontext will be destroyed when function's main context is */
     596             : 
     597             :     /*
     598             :      * Pop the error context stack
     599             :      */
     600       10358 :     error_context_stack = plerrcontext.previous;
     601             : 
     602             :     /*
     603             :      * Return the function's result
     604             :      */
     605       10358 :     return estate.retval;
     606             : }
     607             : 
     608             : 
     609             : /* ----------
     610             :  * plpgsql_exec_trigger     Called by the call handler for
     611             :  *              trigger execution.
     612             :  * ----------
     613             :  */
     614             : HeapTuple
     615        1831 : plpgsql_exec_trigger(PLpgSQL_function *func,
     616             :                      TriggerData *trigdata)
     617             : {
     618             :     PLpgSQL_execstate estate;
     619             :     ErrorContextCallback plerrcontext;
     620             :     int         i;
     621             :     int         rc;
     622             :     PLpgSQL_var *var;
     623             :     PLpgSQL_rec *rec_new,
     624             :                *rec_old;
     625             :     HeapTuple   rettup;
     626             : 
     627             :     /*
     628             :      * Setup the execution state
     629             :      */
     630        1831 :     plpgsql_estate_setup(&estate, func, NULL, NULL);
     631             : 
     632             :     /*
     633             :      * Setup error traceback support for ereport()
     634             :      */
     635        1831 :     plerrcontext.callback = plpgsql_exec_error_callback;
     636        1831 :     plerrcontext.arg = &estate;
     637        1831 :     plerrcontext.previous = error_context_stack;
     638        1831 :     error_context_stack = &plerrcontext;
     639             : 
     640             :     /*
     641             :      * Make local execution copies of all the datums
     642             :      */
     643        1831 :     estate.err_text = gettext_noop("during initialization of execution state");
     644       38636 :     for (i = 0; i < estate.ndatums; i++)
     645       36805 :         estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
     646             : 
     647             :     /*
     648             :      * Put the OLD and NEW tuples into record variables
     649             :      *
     650             :      * We make the tupdescs available in both records even though only one may
     651             :      * have a value.  This allows parsing of record references to succeed in
     652             :      * functions that are used for multiple trigger types.  For example, we
     653             :      * might have a test like "if (TG_OP = 'INSERT' and NEW.foo = 'xyz')",
     654             :      * which should parse regardless of the current trigger type.
     655             :      */
     656        1831 :     rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
     657        1831 :     rec_new->freetup = false;
     658        1831 :     rec_new->tupdesc = trigdata->tg_relation->rd_att;
     659        1831 :     rec_new->freetupdesc = false;
     660        1831 :     rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
     661        1831 :     rec_old->freetup = false;
     662        1831 :     rec_old->tupdesc = trigdata->tg_relation->rd_att;
     663        1831 :     rec_old->freetupdesc = false;
     664             : 
     665        1831 :     if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
     666             :     {
     667             :         /*
     668             :          * Per-statement triggers don't use OLD/NEW variables
     669             :          */
     670         128 :         rec_new->tup = NULL;
     671         128 :         rec_old->tup = NULL;
     672             :     }
     673        1703 :     else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
     674             :     {
     675         911 :         rec_new->tup = trigdata->tg_trigtuple;
     676         911 :         rec_old->tup = NULL;
     677             :     }
     678         792 :     else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
     679             :     {
     680         768 :         rec_new->tup = trigdata->tg_newtuple;
     681         768 :         rec_old->tup = trigdata->tg_trigtuple;
     682             :     }
     683          24 :     else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
     684             :     {
     685          24 :         rec_new->tup = NULL;
     686          24 :         rec_old->tup = trigdata->tg_trigtuple;
     687             :     }
     688             :     else
     689           0 :         elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
     690             : 
     691             :     /* Make transition tables visible to this SPI connection */
     692        1831 :     rc = SPI_register_trigger_data(trigdata);
     693        1831 :     Assert(rc >= 0);
     694             : 
     695             :     /*
     696             :      * Assign the special tg_ variables
     697             :      */
     698             : 
     699        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_op_varno]);
     700        1831 :     if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
     701         970 :         assign_text_var(&estate, var, "INSERT");
     702         861 :     else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
     703         813 :         assign_text_var(&estate, var, "UPDATE");
     704          48 :     else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
     705          46 :         assign_text_var(&estate, var, "DELETE");
     706           2 :     else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
     707           2 :         assign_text_var(&estate, var, "TRUNCATE");
     708             :     else
     709           0 :         elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
     710             : 
     711        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_name_varno]);
     712        1831 :     assign_simple_var(&estate, var,
     713        1831 :                       DirectFunctionCall1(namein,
     714             :                                           CStringGetDatum(trigdata->tg_trigger->tgname)),
     715             :                       false, true);
     716             : 
     717        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
     718        1831 :     if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
     719        1133 :         assign_text_var(&estate, var, "BEFORE");
     720         698 :     else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
     721         657 :         assign_text_var(&estate, var, "AFTER");
     722          41 :     else if (TRIGGER_FIRED_INSTEAD(trigdata->tg_event))
     723          41 :         assign_text_var(&estate, var, "INSTEAD OF");
     724             :     else
     725           0 :         elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
     726             : 
     727        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
     728        1831 :     if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
     729        1703 :         assign_text_var(&estate, var, "ROW");
     730         128 :     else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
     731         128 :         assign_text_var(&estate, var, "STATEMENT");
     732             :     else
     733           0 :         elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
     734             : 
     735        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_relid_varno]);
     736        1831 :     assign_simple_var(&estate, var,
     737        1831 :                       ObjectIdGetDatum(trigdata->tg_relation->rd_id),
     738             :                       false, false);
     739             : 
     740        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_relname_varno]);
     741        1831 :     assign_simple_var(&estate, var,
     742        1831 :                       DirectFunctionCall1(namein,
     743             :                                           CStringGetDatum(RelationGetRelationName(trigdata->tg_relation))),
     744             :                       false, true);
     745             : 
     746        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_table_name_varno]);
     747        1831 :     assign_simple_var(&estate, var,
     748        1831 :                       DirectFunctionCall1(namein,
     749             :                                           CStringGetDatum(RelationGetRelationName(trigdata->tg_relation))),
     750             :                       false, true);
     751             : 
     752        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_table_schema_varno]);
     753        1831 :     assign_simple_var(&estate, var,
     754        1831 :                       DirectFunctionCall1(namein,
     755             :                                           CStringGetDatum(get_namespace_name(
     756             :                                                                              RelationGetNamespace(
     757             :                                                                                                   trigdata->tg_relation)))),
     758             :                       false, true);
     759             : 
     760        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
     761        1831 :     assign_simple_var(&estate, var,
     762        1831 :                       Int16GetDatum(trigdata->tg_trigger->tgnargs),
     763             :                       false, false);
     764             : 
     765        1831 :     var = (PLpgSQL_var *) (estate.datums[func->tg_argv_varno]);
     766        1831 :     if (trigdata->tg_trigger->tgnargs > 0)
     767             :     {
     768             :         /*
     769             :          * For historical reasons, tg_argv[] subscripts start at zero not one.
     770             :          * So we can't use construct_array().
     771             :          */
     772         730 :         int         nelems = trigdata->tg_trigger->tgnargs;
     773             :         Datum      *elems;
     774             :         int         dims[1];
     775             :         int         lbs[1];
     776             : 
     777         730 :         elems = palloc(sizeof(Datum) * nelems);
     778        1463 :         for (i = 0; i < nelems; i++)
     779         733 :             elems[i] = CStringGetTextDatum(trigdata->tg_trigger->tgargs[i]);
     780         730 :         dims[0] = nelems;
     781         730 :         lbs[0] = 0;
     782             : 
     783         730 :         assign_simple_var(&estate, var,
     784         730 :                           PointerGetDatum(construct_md_array(elems, NULL,
     785             :                                                              1, dims, lbs,
     786             :                                                              TEXTOID,
     787             :                                                              -1, false, 'i')),
     788             :                           false, true);
     789             :     }
     790             :     else
     791             :     {
     792        1101 :         assign_simple_var(&estate, var, (Datum) 0, true, false);
     793             :     }
     794             : 
     795        1831 :     estate.err_text = gettext_noop("during function entry");
     796             : 
     797             :     /*
     798             :      * Set the magic variable FOUND to false
     799             :      */
     800        1831 :     exec_set_found(&estate, false);
     801             : 
     802             :     /*
     803             :      * Let the instrumentation plugin peek at this function
     804             :      */
     805        1831 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
     806           0 :         ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
     807             : 
     808             :     /*
     809             :      * Now call the toplevel block of statements
     810             :      */
     811        1831 :     estate.err_text = NULL;
     812        1831 :     estate.err_stmt = (PLpgSQL_stmt *) (func->action);
     813        1831 :     rc = exec_stmt_block(&estate, func->action);
     814        1810 :     if (rc != PLPGSQL_RC_RETURN)
     815             :     {
     816           0 :         estate.err_stmt = NULL;
     817           0 :         estate.err_text = NULL;
     818           0 :         ereport(ERROR,
     819             :                 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
     820             :                  errmsg("control reached end of trigger procedure without RETURN")));
     821             :     }
     822             : 
     823        1810 :     estate.err_stmt = NULL;
     824        1810 :     estate.err_text = gettext_noop("during function exit");
     825             : 
     826        1810 :     if (estate.retisset)
     827           0 :         ereport(ERROR,
     828             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     829             :                  errmsg("trigger procedure cannot return a set")));
     830             : 
     831             :     /*
     832             :      * Check that the returned tuple structure has the same attributes, the
     833             :      * relation that fired the trigger has. A per-statement trigger always
     834             :      * needs to return NULL, so we ignore any return value the function itself
     835             :      * produces (XXX: is this a good idea?)
     836             :      *
     837             :      * XXX This way it is possible, that the trigger returns a tuple where
     838             :      * attributes don't have the correct atttypmod's length. It's up to the
     839             :      * trigger's programmer to ensure that this doesn't happen. Jan
     840             :      */
     841        1810 :     if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
     842         213 :         rettup = NULL;
     843             :     else
     844             :     {
     845             :         TupleConversionMap *tupmap;
     846             : 
     847        1597 :         rettup = (HeapTuple) DatumGetPointer(estate.retval);
     848             :         /* check rowtype compatibility */
     849        1597 :         tupmap = convert_tuples_by_position(estate.rettupdesc,
     850        1597 :                                             trigdata->tg_relation->rd_att,
     851             :                                             gettext_noop("returned row structure does not match the structure of the triggering table"));
     852             :         /* it might need conversion */
     853        1597 :         if (tupmap)
     854           0 :             rettup = do_convert_tuple(rettup, tupmap);
     855             :         /* no need to free map, we're about to return anyway */
     856             : 
     857             :         /* Copy tuple to upper executor memory */
     858        1597 :         rettup = SPI_copytuple(rettup);
     859             :     }
     860             : 
     861             :     /*
     862             :      * Let the instrumentation plugin peek at this function
     863             :      */
     864        1810 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
     865           0 :         ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
     866             : 
     867             :     /* Clean up any leftover temporary memory */
     868        1810 :     plpgsql_destroy_econtext(&estate);
     869        1810 :     exec_eval_cleanup(&estate);
     870             :     /* stmt_mcontext will be destroyed when function's main context is */
     871             : 
     872             :     /*
     873             :      * Pop the error context stack
     874             :      */
     875        1810 :     error_context_stack = plerrcontext.previous;
     876             : 
     877             :     /*
     878             :      * Return the trigger's result
     879             :      */
     880        1810 :     return rettup;
     881             : }
     882             : 
     883             : /* ----------
     884             :  * plpgsql_exec_event_trigger       Called by the call handler for
     885             :  *              event trigger execution.
     886             :  * ----------
     887             :  */
     888             : void
     889          45 : plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
     890             : {
     891             :     PLpgSQL_execstate estate;
     892             :     ErrorContextCallback plerrcontext;
     893             :     int         i;
     894             :     int         rc;
     895             :     PLpgSQL_var *var;
     896             : 
     897             :     /*
     898             :      * Setup the execution state
     899             :      */
     900          45 :     plpgsql_estate_setup(&estate, func, NULL, NULL);
     901             : 
     902             :     /*
     903             :      * Setup error traceback support for ereport()
     904             :      */
     905          45 :     plerrcontext.callback = plpgsql_exec_error_callback;
     906          45 :     plerrcontext.arg = &estate;
     907          45 :     plerrcontext.previous = error_context_stack;
     908          45 :     error_context_stack = &plerrcontext;
     909             : 
     910             :     /*
     911             :      * Make local execution copies of all the datums
     912             :      */
     913          45 :     estate.err_text = gettext_noop("during initialization of execution state");
     914         317 :     for (i = 0; i < estate.ndatums; i++)
     915         272 :         estate.datums[i] = copy_plpgsql_datum(func->datums[i]);
     916             : 
     917             :     /*
     918             :      * Assign the special tg_ variables
     919             :      */
     920          45 :     var = (PLpgSQL_var *) (estate.datums[func->tg_event_varno]);
     921          45 :     assign_text_var(&estate, var, trigdata->event);
     922             : 
     923          45 :     var = (PLpgSQL_var *) (estate.datums[func->tg_tag_varno]);
     924          45 :     assign_text_var(&estate, var, trigdata->tag);
     925             : 
     926             :     /*
     927             :      * Let the instrumentation plugin peek at this function
     928             :      */
     929          45 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
     930           0 :         ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
     931             : 
     932             :     /*
     933             :      * Now call the toplevel block of statements
     934             :      */
     935          45 :     estate.err_text = NULL;
     936          45 :     estate.err_stmt = (PLpgSQL_stmt *) (func->action);
     937          45 :     rc = exec_stmt_block(&estate, func->action);
     938          40 :     if (rc != PLPGSQL_RC_RETURN)
     939             :     {
     940           0 :         estate.err_stmt = NULL;
     941           0 :         estate.err_text = NULL;
     942           0 :         ereport(ERROR,
     943             :                 (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
     944             :                  errmsg("control reached end of trigger procedure without RETURN")));
     945             :     }
     946             : 
     947          40 :     estate.err_stmt = NULL;
     948          40 :     estate.err_text = gettext_noop("during function exit");
     949             : 
     950             :     /*
     951             :      * Let the instrumentation plugin peek at this function
     952             :      */
     953          40 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
     954           0 :         ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
     955             : 
     956             :     /* Clean up any leftover temporary memory */
     957          40 :     plpgsql_destroy_econtext(&estate);
     958          40 :     exec_eval_cleanup(&estate);
     959             :     /* stmt_mcontext will be destroyed when function's main context is */
     960             : 
     961             :     /*
     962             :      * Pop the error context stack
     963             :      */
     964          40 :     error_context_stack = plerrcontext.previous;
     965             : 
     966          40 :     return;
     967             : }
     968             : 
     969             : /*
     970             :  * error context callback to let us supply a call-stack traceback
     971             :  */
     972             : static void
     973        1752 : plpgsql_exec_error_callback(void *arg)
     974             : {
     975        1752 :     PLpgSQL_execstate *estate = (PLpgSQL_execstate *) arg;
     976             : 
     977        1752 :     if (estate->err_text != NULL)
     978             :     {
     979             :         /*
     980             :          * We don't expend the cycles to run gettext() on err_text unless we
     981             :          * actually need it.  Therefore, places that set up err_text should
     982             :          * use gettext_noop() to ensure the strings get recorded in the
     983             :          * message dictionary.
     984             :          *
     985             :          * If both err_text and err_stmt are set, use the err_text as
     986             :          * description, but report the err_stmt's line number.  When err_stmt
     987             :          * is not set, we're in function entry/exit, or some such place not
     988             :          * attached to a specific line number.
     989             :          */
     990           7 :         if (estate->err_stmt != NULL)
     991             :         {
     992             :             /*
     993             :              * translator: last %s is a phrase such as "during statement block
     994             :              * local variable initialization"
     995             :              */
     996           6 :             errcontext("PL/pgSQL function %s line %d %s",
     997           2 :                        estate->func->fn_signature,
     998           2 :                        estate->err_stmt->lineno,
     999             :                        _(estate->err_text));
    1000             :         }
    1001             :         else
    1002             :         {
    1003             :             /*
    1004             :              * translator: last %s is a phrase such as "while storing call
    1005             :              * arguments into local variables"
    1006             :              */
    1007          10 :             errcontext("PL/pgSQL function %s %s",
    1008           5 :                        estate->func->fn_signature,
    1009             :                        _(estate->err_text));
    1010             :         }
    1011             :     }
    1012        1745 :     else if (estate->err_stmt != NULL)
    1013             :     {
    1014             :         /* translator: last %s is a plpgsql statement type name */
    1015        5232 :         errcontext("PL/pgSQL function %s line %d at %s",
    1016        1744 :                    estate->func->fn_signature,
    1017        1744 :                    estate->err_stmt->lineno,
    1018             :                    plpgsql_stmt_typename(estate->err_stmt));
    1019             :     }
    1020             :     else
    1021           2 :         errcontext("PL/pgSQL function %s",
    1022           1 :                    estate->func->fn_signature);
    1023        1752 : }
    1024             : 
    1025             : 
    1026             : /* ----------
    1027             :  * Support function for initializing local execution variables
    1028             :  * ----------
    1029             :  */
    1030             : static PLpgSQL_datum *
    1031       66617 : copy_plpgsql_datum(PLpgSQL_datum *datum)
    1032             : {
    1033             :     PLpgSQL_datum *result;
    1034             : 
    1035       66617 :     switch (datum->dtype)
    1036             :     {
    1037             :         case PLPGSQL_DTYPE_VAR:
    1038             :             {
    1039       48409 :                 PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
    1040             : 
    1041       48409 :                 memcpy(new, datum, sizeof(PLpgSQL_var));
    1042             :                 /* should be preset to null/non-freeable */
    1043       48409 :                 Assert(new->isnull);
    1044       48409 :                 Assert(!new->freeval);
    1045             : 
    1046       48409 :                 result = (PLpgSQL_datum *) new;
    1047             :             }
    1048       48409 :             break;
    1049             : 
    1050             :         case PLPGSQL_DTYPE_REC:
    1051             :             {
    1052        4180 :                 PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
    1053             : 
    1054        4180 :                 memcpy(new, datum, sizeof(PLpgSQL_rec));
    1055             :                 /* should be preset to null/non-freeable */
    1056        4180 :                 Assert(new->tup == NULL);
    1057        4180 :                 Assert(new->tupdesc == NULL);
    1058        4180 :                 Assert(!new->freetup);
    1059        4180 :                 Assert(!new->freetupdesc);
    1060             : 
    1061        4180 :                 result = (PLpgSQL_datum *) new;
    1062             :             }
    1063        4180 :             break;
    1064             : 
    1065             :         case PLPGSQL_DTYPE_ROW:
    1066             :         case PLPGSQL_DTYPE_RECFIELD:
    1067             :         case PLPGSQL_DTYPE_ARRAYELEM:
    1068             : 
    1069             :             /*
    1070             :              * These datum records are read-only at runtime, so no need to
    1071             :              * copy them (well, ARRAYELEM contains some cached type data, but
    1072             :              * we'd just as soon centralize the caching anyway)
    1073             :              */
    1074       14028 :             result = datum;
    1075       14028 :             break;
    1076             : 
    1077             :         default:
    1078           0 :             elog(ERROR, "unrecognized dtype: %d", datum->dtype);
    1079             :             result = NULL;      /* keep compiler quiet */
    1080             :             break;
    1081             :     }
    1082             : 
    1083       66617 :     return result;
    1084             : }
    1085             : 
    1086             : /*
    1087             :  * Create a memory context for statement-lifespan variables, if we don't
    1088             :  * have one already.  It will be a child of stmt_mcontext_parent, which is
    1089             :  * either the function's main context or a pushed-down outer stmt_mcontext.
    1090             :  */
    1091             : static MemoryContext
    1092        2718 : get_stmt_mcontext(PLpgSQL_execstate *estate)
    1093             : {
    1094        2718 :     if (estate->stmt_mcontext == NULL)
    1095             :     {
    1096        1142 :         estate->stmt_mcontext =
    1097        1142 :             AllocSetContextCreate(estate->stmt_mcontext_parent,
    1098             :                                   "PLpgSQL per-statement data",
    1099             :                                   ALLOCSET_DEFAULT_SIZES);
    1100             :     }
    1101        2718 :     return estate->stmt_mcontext;
    1102             : }
    1103             : 
    1104             : /*
    1105             :  * Push down the current stmt_mcontext so that called statements won't use it.
    1106             :  * This is needed by statements that have statement-lifespan data and need to
    1107             :  * preserve it across some inner statements.  The caller should eventually do
    1108             :  * pop_stmt_mcontext().
    1109             :  */
    1110             : static void
    1111          15 : push_stmt_mcontext(PLpgSQL_execstate *estate)
    1112             : {
    1113             :     /* Should have done get_stmt_mcontext() first */
    1114          15 :     Assert(estate->stmt_mcontext != NULL);
    1115             :     /* Assert we've not messed up the stack linkage */
    1116          15 :     Assert(MemoryContextGetParent(estate->stmt_mcontext) == estate->stmt_mcontext_parent);
    1117             :     /* Push it down to become the parent of any nested stmt mcontext */
    1118          15 :     estate->stmt_mcontext_parent = estate->stmt_mcontext;
    1119             :     /* And make it not available for use directly */
    1120          15 :     estate->stmt_mcontext = NULL;
    1121          15 : }
    1122             : 
    1123             : /*
    1124             :  * Undo push_stmt_mcontext().  We assume this is done just before or after
    1125             :  * resetting the caller's stmt_mcontext; since that action will also delete
    1126             :  * any child contexts, there's no need to explicitly delete whatever context
    1127             :  * might currently be estate->stmt_mcontext.
    1128             :  */
    1129             : static void
    1130         247 : pop_stmt_mcontext(PLpgSQL_execstate *estate)
    1131             : {
    1132             :     /* We need only pop the stack */
    1133         247 :     estate->stmt_mcontext = estate->stmt_mcontext_parent;
    1134         247 :     estate->stmt_mcontext_parent = MemoryContextGetParent(estate->stmt_mcontext);
    1135         247 : }
    1136             : 
    1137             : 
    1138             : /*
    1139             :  * Subroutine for exec_stmt_block: does any condition in the condition list
    1140             :  * match the current exception?
    1141             :  */
    1142             : static bool
    1143         249 : exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond)
    1144             : {
    1145         259 :     for (; cond != NULL; cond = cond->next)
    1146             :     {
    1147         250 :         int         sqlerrstate = cond->sqlerrstate;
    1148             : 
    1149             :         /*
    1150             :          * OTHERS matches everything *except* query-canceled and
    1151             :          * assert-failure.  If you're foolish enough, you can match those
    1152             :          * explicitly.
    1153             :          */
    1154         250 :         if (sqlerrstate == 0)
    1155             :         {
    1156         413 :             if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
    1157         206 :                 edata->sqlerrcode != ERRCODE_ASSERT_FAILURE)
    1158         205 :                 return true;
    1159             :         }
    1160             :         /* Exact match? */
    1161          43 :         else if (edata->sqlerrcode == sqlerrstate)
    1162          33 :             return true;
    1163             :         /* Category match? */
    1164          13 :         else if (ERRCODE_IS_CATEGORY(sqlerrstate) &&
    1165           3 :                  ERRCODE_TO_CATEGORY(edata->sqlerrcode) == sqlerrstate)
    1166           2 :             return true;
    1167             :     }
    1168           9 :     return false;
    1169             : }
    1170             : 
    1171             : 
    1172             : /* ----------
    1173             :  * exec_stmt_block          Execute a block of statements
    1174             :  * ----------
    1175             :  */
    1176             : static int
    1177       12607 : exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
    1178             : {
    1179       12607 :     volatile int rc = -1;
    1180             :     int         i;
    1181             :     int         n;
    1182             : 
    1183             :     /*
    1184             :      * First initialize all variables declared in this block
    1185             :      */
    1186       12607 :     estate->err_text = gettext_noop("during statement block local variable initialization");
    1187             : 
    1188       14071 :     for (i = 0; i < block->n_initvars; i++)
    1189             :     {
    1190        1466 :         n = block->initvarnos[i];
    1191             : 
    1192        1466 :         switch (estate->datums[n]->dtype)
    1193             :         {
    1194             :             case PLPGSQL_DTYPE_VAR:
    1195             :                 {
    1196        1466 :                     PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]);
    1197             : 
    1198             :                     /*
    1199             :                      * Free any old value, in case re-entering block, and
    1200             :                      * initialize to NULL
    1201             :                      */
    1202        1466 :                     assign_simple_var(estate, var, (Datum) 0, true, false);
    1203             : 
    1204        1466 :                     if (var->default_val == NULL)
    1205             :                     {
    1206             :                         /*
    1207             :                          * If needed, give the datatype a chance to reject
    1208             :                          * NULLs, by assigning a NULL to the variable. We
    1209             :                          * claim the value is of type UNKNOWN, not the var's
    1210             :                          * datatype, else coercion will be skipped. (Do this
    1211             :                          * before the notnull check to be consistent with
    1212             :                          * exec_assign_value.)
    1213             :                          */
    1214        1343 :                         if (var->datatype->typtype == TYPTYPE_DOMAIN)
    1215          15 :                             exec_assign_value(estate,
    1216             :                                               (PLpgSQL_datum *) var,
    1217             :                                               (Datum) 0,
    1218             :                                               true,
    1219             :                                               UNKNOWNOID,
    1220             :                                               -1);
    1221             : 
    1222        1342 :                         if (var->notnull)
    1223           0 :                             ereport(ERROR,
    1224             :                                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    1225             :                                      errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
    1226             :                                             var->refname)));
    1227             :                     }
    1228             :                     else
    1229             :                     {
    1230         123 :                         exec_assign_expr(estate, (PLpgSQL_datum *) var,
    1231             :                                          var->default_val);
    1232             :                     }
    1233             :                 }
    1234        1464 :                 break;
    1235             : 
    1236             :             case PLPGSQL_DTYPE_REC:
    1237             :                 {
    1238           0 :                     PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[n]);
    1239             : 
    1240           0 :                     if (rec->freetup)
    1241             :                     {
    1242           0 :                         heap_freetuple(rec->tup);
    1243           0 :                         rec->freetup = false;
    1244             :                     }
    1245           0 :                     if (rec->freetupdesc)
    1246             :                     {
    1247           0 :                         FreeTupleDesc(rec->tupdesc);
    1248           0 :                         rec->freetupdesc = false;
    1249             :                     }
    1250           0 :                     rec->tup = NULL;
    1251           0 :                     rec->tupdesc = NULL;
    1252             :                 }
    1253           0 :                 break;
    1254             : 
    1255             :             case PLPGSQL_DTYPE_RECFIELD:
    1256             :             case PLPGSQL_DTYPE_ARRAYELEM:
    1257           0 :                 break;
    1258             : 
    1259             :             default:
    1260           0 :                 elog(ERROR, "unrecognized dtype: %d",
    1261             :                      estate->datums[n]->dtype);
    1262             :         }
    1263             :     }
    1264             : 
    1265       12605 :     if (block->exceptions)
    1266             :     {
    1267             :         /*
    1268             :          * Execute the statements in the block's body inside a sub-transaction
    1269             :          */
    1270         252 :         MemoryContext oldcontext = CurrentMemoryContext;
    1271         252 :         ResourceOwner oldowner = CurrentResourceOwner;
    1272         252 :         ExprContext *old_eval_econtext = estate->eval_econtext;
    1273         252 :         ErrorData  *save_cur_error = estate->cur_error;
    1274             :         MemoryContext stmt_mcontext;
    1275             : 
    1276         252 :         estate->err_text = gettext_noop("during statement block entry");
    1277             : 
    1278             :         /*
    1279             :          * We will need a stmt_mcontext to hold the error data if an error
    1280             :          * occurs.  It seems best to force it to exist before entering the
    1281             :          * subtransaction, so that we reduce the risk of out-of-memory during
    1282             :          * error recovery, and because this greatly simplifies restoring the
    1283             :          * stmt_mcontext stack to the correct state after an error.  We can
    1284             :          * ameliorate the cost of this by allowing the called statements to
    1285             :          * use this mcontext too; so we don't push it down here.
    1286             :          */
    1287         252 :         stmt_mcontext = get_stmt_mcontext(estate);
    1288             : 
    1289         252 :         BeginInternalSubTransaction(NULL);
    1290             :         /* Want to run statements inside function's memory context */
    1291         252 :         MemoryContextSwitchTo(oldcontext);
    1292             : 
    1293         252 :         PG_TRY();
    1294             :         {
    1295             :             /*
    1296             :              * We need to run the block's statements with a new eval_econtext
    1297             :              * that belongs to the current subtransaction; if we try to use
    1298             :              * the outer econtext then ExprContext shutdown callbacks will be
    1299             :              * called at the wrong times.
    1300             :              */
    1301         252 :             plpgsql_create_econtext(estate);
    1302             : 
    1303         252 :             estate->err_text = NULL;
    1304             : 
    1305             :             /* Run the block's statements */
    1306         252 :             rc = exec_stmts(estate, block->body);
    1307             : 
    1308           9 :             estate->err_text = gettext_noop("during statement block exit");
    1309             : 
    1310             :             /*
    1311             :              * If the block ended with RETURN, we may need to copy the return
    1312             :              * value out of the subtransaction eval_context.  This is
    1313             :              * currently only needed for scalar result types --- rowtype
    1314             :              * values will always exist in the function's main memory context,
    1315             :              * cf. exec_stmt_return().  We can avoid a physical copy if the
    1316             :              * value happens to be a R/W expanded object.
    1317             :              */
    1318           9 :             if (rc == PLPGSQL_RC_RETURN &&
    1319           0 :                 !estate->retisset &&
    1320           0 :                 !estate->retisnull &&
    1321           0 :                 estate->rettupdesc == NULL)
    1322             :             {
    1323             :                 int16       resTypLen;
    1324             :                 bool        resTypByVal;
    1325             : 
    1326           0 :                 get_typlenbyval(estate->rettype, &resTypLen, &resTypByVal);
    1327           0 :                 estate->retval = datumTransfer(estate->retval,
    1328             :                                                resTypByVal, resTypLen);
    1329             :             }
    1330             : 
    1331             :             /* Commit the inner transaction, return to outer xact context */
    1332           9 :             ReleaseCurrentSubTransaction();
    1333           9 :             MemoryContextSwitchTo(oldcontext);
    1334           9 :             CurrentResourceOwner = oldowner;
    1335             : 
    1336             :             /* Assert that the stmt_mcontext stack is unchanged */
    1337           9 :             Assert(stmt_mcontext == estate->stmt_mcontext);
    1338             : 
    1339             :             /*
    1340             :              * Revert to outer eval_econtext.  (The inner one was
    1341             :              * automatically cleaned up during subxact exit.)
    1342             :              */
    1343           9 :             estate->eval_econtext = old_eval_econtext;
    1344             :         }
    1345         243 :         PG_CATCH();
    1346             :         {
    1347             :             ErrorData  *edata;
    1348             :             ListCell   *e;
    1349             : 
    1350         243 :             estate->err_text = gettext_noop("during exception cleanup");
    1351             : 
    1352             :             /* Save error info in our stmt_mcontext */
    1353         243 :             MemoryContextSwitchTo(stmt_mcontext);
    1354         243 :             edata = CopyErrorData();
    1355         243 :             FlushErrorState();
    1356             : 
    1357             :             /* Abort the inner transaction */
    1358         243 :             RollbackAndReleaseCurrentSubTransaction();
    1359         243 :             MemoryContextSwitchTo(oldcontext);
    1360         243 :             CurrentResourceOwner = oldowner;
    1361             : 
    1362             :             /*
    1363             :              * Set up the stmt_mcontext stack as though we had restored our
    1364             :              * previous state and then done push_stmt_mcontext().  The push is
    1365             :              * needed so that statements in the exception handler won't
    1366             :              * clobber the error data that's in our stmt_mcontext.
    1367             :              */
    1368         243 :             estate->stmt_mcontext_parent = stmt_mcontext;
    1369         243 :             estate->stmt_mcontext = NULL;
    1370             : 
    1371             :             /*
    1372             :              * Now we can delete any nested stmt_mcontexts that might have
    1373             :              * been created as children of ours.  (Note: we do not immediately
    1374             :              * release any statement-lifespan data that might have been left
    1375             :              * behind in stmt_mcontext itself.  We could attempt that by doing
    1376             :              * a MemoryContextReset on it before collecting the error data
    1377             :              * above, but it seems too risky to do any significant amount of
    1378             :              * work before collecting the error.)
    1379             :              */
    1380         243 :             MemoryContextDeleteChildren(stmt_mcontext);
    1381             : 
    1382             :             /* Revert to outer eval_econtext */
    1383         243 :             estate->eval_econtext = old_eval_econtext;
    1384             : 
    1385             :             /*
    1386             :              * Must clean up the econtext too.  However, any tuple table made
    1387             :              * in the subxact will have been thrown away by SPI during subxact
    1388             :              * abort, so we don't need to (and mustn't try to) free the
    1389             :              * eval_tuptable.
    1390             :              */
    1391         243 :             estate->eval_tuptable = NULL;
    1392         243 :             exec_eval_cleanup(estate);
    1393             : 
    1394             :             /* Look for a matching exception handler */
    1395         252 :             foreach(e, block->exceptions->exc_list)
    1396             :             {
    1397         249 :                 PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(e);
    1398             : 
    1399         249 :                 if (exception_matches_conditions(edata, exception->conditions))
    1400             :                 {
    1401             :                     /*
    1402             :                      * Initialize the magic SQLSTATE and SQLERRM variables for
    1403             :                      * the exception block; this also frees values from any
    1404             :                      * prior use of the same exception. We needn't do this
    1405             :                      * until we have found a matching exception.
    1406             :                      */
    1407             :                     PLpgSQL_var *state_var;
    1408             :                     PLpgSQL_var *errm_var;
    1409             : 
    1410         240 :                     state_var = (PLpgSQL_var *)
    1411         240 :                         estate->datums[block->exceptions->sqlstate_varno];
    1412         240 :                     errm_var = (PLpgSQL_var *)
    1413         240 :                         estate->datums[block->exceptions->sqlerrm_varno];
    1414             : 
    1415         240 :                     assign_text_var(estate, state_var,
    1416         240 :                                     unpack_sql_state(edata->sqlerrcode));
    1417         240 :                     assign_text_var(estate, errm_var, edata->message);
    1418             : 
    1419             :                     /*
    1420             :                      * Also set up cur_error so the error data is accessible
    1421             :                      * inside the handler.
    1422             :                      */
    1423         240 :                     estate->cur_error = edata;
    1424             : 
    1425         240 :                     estate->err_text = NULL;
    1426             : 
    1427         240 :                     rc = exec_stmts(estate, exception->action);
    1428             : 
    1429         235 :                     break;
    1430             :                 }
    1431             :             }
    1432             : 
    1433             :             /*
    1434             :              * Restore previous state of cur_error, whether or not we executed
    1435             :              * a handler.  This is needed in case an error got thrown from
    1436             :              * some inner block's exception handler.
    1437             :              */
    1438         238 :             estate->cur_error = save_cur_error;
    1439             : 
    1440             :             /* If no match found, re-throw the error */
    1441         238 :             if (e == NULL)
    1442           3 :                 ReThrowError(edata);
    1443             : 
    1444             :             /* Restore stmt_mcontext stack and release the error data */
    1445         235 :             pop_stmt_mcontext(estate);
    1446         235 :             MemoryContextReset(stmt_mcontext);
    1447             :         }
    1448         244 :         PG_END_TRY();
    1449             : 
    1450         244 :         Assert(save_cur_error == estate->cur_error);
    1451             :     }
    1452             :     else
    1453             :     {
    1454             :         /*
    1455             :          * Just execute the statements in the block's body
    1456             :          */
    1457       12353 :         estate->err_text = NULL;
    1458             : 
    1459       12353 :         rc = exec_stmts(estate, block->body);
    1460             :     }
    1461             : 
    1462       12485 :     estate->err_text = NULL;
    1463             : 
    1464             :     /*
    1465             :      * Handle the return code.
    1466             :      */
    1467       12485 :     switch (rc)
    1468             :     {
    1469             :         case PLPGSQL_RC_OK:
    1470             :         case PLPGSQL_RC_RETURN:
    1471             :         case PLPGSQL_RC_CONTINUE:
    1472       12484 :             return rc;
    1473             : 
    1474             :         case PLPGSQL_RC_EXIT:
    1475             : 
    1476             :             /*
    1477             :              * This is intentionally different from the handling of RC_EXIT
    1478             :              * for loops: to match a block, we require a match by label.
    1479             :              */
    1480           1 :             if (estate->exitlabel == NULL)
    1481           0 :                 return PLPGSQL_RC_EXIT;
    1482           1 :             if (block->label == NULL)
    1483           0 :                 return PLPGSQL_RC_EXIT;
    1484           1 :             if (strcmp(block->label, estate->exitlabel) != 0)
    1485           0 :                 return PLPGSQL_RC_EXIT;
    1486           1 :             estate->exitlabel = NULL;
    1487           1 :             return PLPGSQL_RC_OK;
    1488             : 
    1489             :         default:
    1490           0 :             elog(ERROR, "unrecognized rc: %d", rc);
    1491             :     }
    1492             : 
    1493             :     return PLPGSQL_RC_OK;
    1494             : }
    1495             : 
    1496             : 
    1497             : /* ----------
    1498             :  * exec_stmts           Iterate over a list of statements
    1499             :  *              as long as their return code is OK
    1500             :  * ----------
    1501             :  */
    1502             : static int
    1503       30575 : exec_stmts(PLpgSQL_execstate *estate, List *stmts)
    1504             : {
    1505             :     ListCell   *s;
    1506             : 
    1507       30575 :     if (stmts == NIL)
    1508             :     {
    1509             :         /*
    1510             :          * Ensure we do a CHECK_FOR_INTERRUPTS() even though there is no
    1511             :          * statement.  This prevents hangup in a tight loop if, for instance,
    1512             :          * there is a LOOP construct with an empty body.
    1513             :          */
    1514        7459 :         CHECK_FOR_INTERRUPTS();
    1515        7459 :         return PLPGSQL_RC_OK;
    1516             :     }
    1517             : 
    1518       39734 :     foreach(s, stmts)
    1519             :     {
    1520       35038 :         PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);
    1521       35038 :         int         rc = exec_stmt(estate, stmt);
    1522             : 
    1523       34643 :         if (rc != PLPGSQL_RC_OK)
    1524       18025 :             return rc;
    1525             :     }
    1526             : 
    1527        4696 :     return PLPGSQL_RC_OK;
    1528             : }
    1529             : 
    1530             : 
    1531             : /* ----------
    1532             :  * exec_stmt            Distribute one statement to the statements
    1533             :  *              type specific execution function.
    1534             :  * ----------
    1535             :  */
    1536             : static int
    1537       35038 : exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
    1538             : {
    1539             :     PLpgSQL_stmt *save_estmt;
    1540       35038 :     int         rc = -1;
    1541             : 
    1542       35038 :     save_estmt = estate->err_stmt;
    1543       35038 :     estate->err_stmt = stmt;
    1544             : 
    1545             :     /* Let the plugin know that we are about to execute this statement */
    1546       35038 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
    1547           0 :         ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
    1548             : 
    1549       35038 :     CHECK_FOR_INTERRUPTS();
    1550             : 
    1551       35038 :     switch (stmt->cmd_type)
    1552             :     {
    1553             :         case PLPGSQL_STMT_BLOCK:
    1554         281 :             rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
    1555         271 :             break;
    1556             : 
    1557             :         case PLPGSQL_STMT_ASSIGN:
    1558        2656 :             rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
    1559        2626 :             break;
    1560             : 
    1561             :         case PLPGSQL_STMT_PERFORM:
    1562         236 :             rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
    1563          28 :             break;
    1564             : 
    1565             :         case PLPGSQL_STMT_GETDIAG:
    1566          16 :             rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
    1567          15 :             break;
    1568             : 
    1569             :         case PLPGSQL_STMT_IF:
    1570       14528 :             rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
    1571       14496 :             break;
    1572             : 
    1573             :         case PLPGSQL_STMT_CASE:
    1574          15 :             rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
    1575          12 :             break;
    1576             : 
    1577             :         case PLPGSQL_STMT_LOOP:
    1578          17 :             rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
    1579          17 :             break;
    1580             : 
    1581             :         case PLPGSQL_STMT_WHILE:
    1582           7 :             rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
    1583           7 :             break;
    1584             : 
    1585             :         case PLPGSQL_STMT_FORI:
    1586          83 :             rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
    1587          83 :             break;
    1588             : 
    1589             :         case PLPGSQL_STMT_FORS:
    1590         174 :             rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
    1591         169 :             break;
    1592             : 
    1593             :         case PLPGSQL_STMT_FORC:
    1594           6 :             rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
    1595           6 :             break;
    1596             : 
    1597             :         case PLPGSQL_STMT_FOREACH_A:
    1598          15 :             rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
    1599          12 :             break;
    1600             : 
    1601             :         case PLPGSQL_STMT_EXIT:
    1602         190 :             rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
    1603         190 :             break;
    1604             : 
    1605             :         case PLPGSQL_STMT_RETURN:
    1606       12221 :             rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
    1607       12213 :             break;
    1608             : 
    1609             :         case PLPGSQL_STMT_RETURN_NEXT:
    1610         156 :             rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
    1611         156 :             break;
    1612             : 
    1613             :         case PLPGSQL_STMT_RETURN_QUERY:
    1614          25 :             rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
    1615          25 :             break;
    1616             : 
    1617             :         case PLPGSQL_STMT_RAISE:
    1618        1334 :             rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
    1619        1281 :             break;
    1620             : 
    1621             :         case PLPGSQL_STMT_ASSERT:
    1622           6 :             rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
    1623           2 :             break;
    1624             : 
    1625             :         case PLPGSQL_STMT_EXECSQL:
    1626        1899 :             rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
    1627        1882 :             break;
    1628             : 
    1629             :         case PLPGSQL_STMT_DYNEXECUTE:
    1630         583 :             rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
    1631         564 :             break;
    1632             : 
    1633             :         case PLPGSQL_STMT_DYNFORS:
    1634         503 :             rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
    1635         503 :             break;
    1636             : 
    1637             :         case PLPGSQL_STMT_OPEN:
    1638          19 :             rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
    1639          18 :             break;
    1640             : 
    1641             :         case PLPGSQL_STMT_FETCH:
    1642          56 :             rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
    1643          55 :             break;
    1644             : 
    1645             :         case PLPGSQL_STMT_CLOSE:
    1646          12 :             rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
    1647          12 :             break;
    1648             : 
    1649             :         default:
    1650           0 :             estate->err_stmt = save_estmt;
    1651           0 :             elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
    1652             :     }
    1653             : 
    1654             :     /* Let the plugin know that we have finished executing this statement */
    1655       34643 :     if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
    1656           0 :         ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
    1657             : 
    1658       34643 :     estate->err_stmt = save_estmt;
    1659             : 
    1660       34643 :     return rc;
    1661             : }
    1662             : 
    1663             : 
    1664             : /* ----------
    1665             :  * exec_stmt_assign         Evaluate an expression and
    1666             :  *                  put the result into a variable.
    1667             :  * ----------
    1668             :  */
    1669             : static int
    1670        2656 : exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
    1671             : {
    1672        2656 :     Assert(stmt->varno >= 0);
    1673             : 
    1674        2656 :     exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
    1675             : 
    1676        2626 :     return PLPGSQL_RC_OK;
    1677             : }
    1678             : 
    1679             : /* ----------
    1680             :  * exec_stmt_perform        Evaluate query and discard result (but set
    1681             :  *                          FOUND depending on whether at least one row
    1682             :  *                          was returned).
    1683             :  * ----------
    1684             :  */
    1685             : static int
    1686         236 : exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
    1687             : {
    1688         236 :     PLpgSQL_expr *expr = stmt->expr;
    1689             : 
    1690         236 :     (void) exec_run_select(estate, expr, 0, NULL);
    1691          28 :     exec_set_found(estate, (estate->eval_processed != 0));
    1692          28 :     exec_eval_cleanup(estate);
    1693             : 
    1694          28 :     return PLPGSQL_RC_OK;
    1695             : }
    1696             : 
    1697             : /* ----------
    1698             :  * exec_stmt_getdiag                    Put internal PG information into
    1699             :  *                                      specified variables.
    1700             :  * ----------
    1701             :  */
    1702             : static int
    1703          16 : exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
    1704             : {
    1705             :     ListCell   *lc;
    1706             : 
    1707             :     /*
    1708             :      * GET STACKED DIAGNOSTICS is only valid inside an exception handler.
    1709             :      *
    1710             :      * Note: we trust the grammar to have disallowed the relevant item kinds
    1711             :      * if not is_stacked, otherwise we'd dump core below.
    1712             :      */
    1713          16 :     if (stmt->is_stacked && estate->cur_error == NULL)
    1714           1 :         ereport(ERROR,
    1715             :                 (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
    1716             :                  errmsg("GET STACKED DIAGNOSTICS cannot be used outside an exception handler")));
    1717             : 
    1718          38 :     foreach(lc, stmt->diag_items)
    1719             :     {
    1720          23 :         PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
    1721          23 :         PLpgSQL_datum *var = estate->datums[diag_item->target];
    1722             : 
    1723          23 :         switch (diag_item->kind)
    1724             :         {
    1725             :             case PLPGSQL_GETDIAG_ROW_COUNT:
    1726           4 :                 exec_assign_value(estate, var,
    1727           4 :                                   UInt64GetDatum(estate->eval_processed),
    1728             :                                   false, INT8OID, -1);
    1729           4 :                 break;
    1730             : 
    1731             :             case PLPGSQL_GETDIAG_RESULT_OID:
    1732           0 :                 exec_assign_value(estate, var,
    1733             :                                   ObjectIdGetDatum(estate->eval_lastoid),
    1734             :                                   false, OIDOID, -1);
    1735           0 :                 break;
    1736             : 
    1737             :             case PLPGSQL_GETDIAG_ERROR_CONTEXT:
    1738           1 :                 exec_assign_c_string(estate, var,
    1739           1 :                                      estate->cur_error->context);
    1740           1 :                 break;
    1741             : 
    1742             :             case PLPGSQL_GETDIAG_ERROR_DETAIL:
    1743           1 :                 exec_assign_c_string(estate, var,
    1744           1 :                                      estate->cur_error->detail);
    1745           1 :                 break;
    1746             : 
    1747             :             case PLPGSQL_GETDIAG_ERROR_HINT:
    1748           1 :                 exec_assign_c_string(estate, var,
    1749           1 :                                      estate->cur_error->hint);
    1750           1 :                 break;
    1751             : 
    1752             :             case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
    1753           1 :                 exec_assign_c_string(estate, var,
    1754           1 :                                      unpack_sql_state(estate->cur_error->sqlerrcode));
    1755           1 :                 break;
    1756             : 
    1757             :             case PLPGSQL_GETDIAG_COLUMN_NAME:
    1758           1 :                 exec_assign_c_string(estate, var,
    1759           1 :                                      estate->cur_error->column_name);
    1760           1 :                 break;
    1761             : 
    1762             :             case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
    1763           1 :                 exec_assign_c_string(estate, var,
    1764           1 :                                      estate->cur_error->constraint_name);
    1765           1 :                 break;
    1766             : 
    1767             :             case PLPGSQL_GETDIAG_DATATYPE_NAME:
    1768           1 :                 exec_assign_c_string(estate, var,
    1769           1 :                                      estate->cur_error->datatype_name);
    1770           1 :                 break;
    1771             : 
    1772             :             case PLPGSQL_GETDIAG_MESSAGE_TEXT:
    1773           2 :                 exec_assign_c_string(estate, var,
    1774           2 :                                      estate->cur_error->message);
    1775           2 :                 break;
    1776             : 
    1777             :             case PLPGSQL_GETDIAG_TABLE_NAME:
    1778           1 :                 exec_assign_c_string(estate, var,
    1779           1 :                                      estate->cur_error->table_name);
    1780           1 :                 break;
    1781             : 
    1782             :             case PLPGSQL_GETDIAG_SCHEMA_NAME:
    1783           1 :                 exec_assign_c_string(estate, var,
    1784           1 :                                      estate->cur_error->schema_name);
    1785           1 :                 break;
    1786             : 
    1787             :             case PLPGSQL_GETDIAG_CONTEXT:
    1788             :                 {
    1789             :                     char       *contextstackstr;
    1790             :                     MemoryContext oldcontext;
    1791             : 
    1792             :                     /* Use eval_mcontext for short-lived string */
    1793           8 :                     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    1794           8 :                     contextstackstr = GetErrorContextStack();
    1795           8 :                     MemoryContextSwitchTo(oldcontext);
    1796             : 
    1797           8 :                     exec_assign_c_string(estate, var, contextstackstr);
    1798             :                 }
    1799           8 :                 break;
    1800             : 
    1801             :             default:
    1802           0 :                 elog(ERROR, "unrecognized diagnostic item kind: %d",
    1803             :                      diag_item->kind);
    1804             :         }
    1805             :     }
    1806             : 
    1807          15 :     exec_eval_cleanup(estate);
    1808             : 
    1809          15 :     return PLPGSQL_RC_OK;
    1810             : }
    1811             : 
    1812             : /* ----------
    1813             :  * exec_stmt_if             Evaluate a bool expression and
    1814             :  *                  execute the true or false body
    1815             :  *                  conditionally.
    1816             :  * ----------
    1817             :  */
    1818             : static int
    1819       14528 : exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
    1820             : {
    1821             :     bool        value;
    1822             :     bool        isnull;
    1823             :     ListCell   *lc;
    1824             : 
    1825       14528 :     value = exec_eval_boolean(estate, stmt->cond, &isnull);
    1826       14528 :     exec_eval_cleanup(estate);
    1827       14528 :     if (!isnull && value)
    1828        6612 :         return exec_stmts(estate, stmt->then_body);
    1829             : 
    1830        7917 :     foreach(lc, stmt->elsif_list)
    1831             :     {
    1832          35 :         PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(lc);
    1833             : 
    1834          35 :         value = exec_eval_boolean(estate, elif->cond, &isnull);
    1835          35 :         exec_eval_cleanup(estate);
    1836          35 :         if (!isnull && value)
    1837          34 :             return exec_stmts(estate, elif->stmts);
    1838             :     }
    1839             : 
    1840        7882 :     return exec_stmts(estate, stmt->else_body);
    1841             : }
    1842             : 
    1843             : 
    1844             : /*-----------
    1845             :  * exec_stmt_case
    1846             :  *-----------
    1847             :  */
    1848             : static int
    1849          15 : exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
    1850             : {
    1851          15 :     PLpgSQL_var *t_var = NULL;
    1852             :     bool        isnull;
    1853             :     ListCell   *l;
    1854             : 
    1855          15 :     if (stmt->t_expr != NULL)
    1856             :     {
    1857             :         /* simple case */
    1858             :         Datum       t_val;
    1859             :         Oid         t_typoid;
    1860             :         int32       t_typmod;
    1861             : 
    1862          11 :         t_val = exec_eval_expr(estate, stmt->t_expr,
    1863             :                                &isnull, &t_typoid, &t_typmod);
    1864             : 
    1865          11 :         t_var = (PLpgSQL_var *) estate->datums[stmt->t_varno];
    1866             : 
    1867             :         /*
    1868             :          * When expected datatype is different from real, change it. Note that
    1869             :          * what we're modifying here is an execution copy of the datum, so
    1870             :          * this doesn't affect the originally stored function parse tree. (In
    1871             :          * theory, if the expression datatype keeps changing during execution,
    1872             :          * this could cause a function-lifespan memory leak.  Doesn't seem
    1873             :          * worth worrying about though.)
    1874             :          */
    1875          11 :         if (t_var->datatype->typoid != t_typoid ||
    1876           0 :             t_var->datatype->atttypmod != t_typmod)
    1877          11 :             t_var->datatype = plpgsql_build_datatype(t_typoid,
    1878             :                                                      t_typmod,
    1879          11 :                                                      estate->func->fn_input_collation);
    1880             : 
    1881             :         /* now we can assign to the variable */
    1882          11 :         exec_assign_value(estate,
    1883             :                           (PLpgSQL_datum *) t_var,
    1884             :                           t_val,
    1885             :                           isnull,
    1886             :                           t_typoid,
    1887             :                           t_typmod);
    1888             : 
    1889          11 :         exec_eval_cleanup(estate);
    1890             :     }
    1891             : 
    1892             :     /* Now search for a successful WHEN clause */
    1893          53 :     foreach(l, stmt->case_when_list)
    1894             :     {
    1895          48 :         PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
    1896             :         bool        value;
    1897             : 
    1898          48 :         value = exec_eval_boolean(estate, cwt->expr, &isnull);
    1899          48 :         exec_eval_cleanup(estate);
    1900          48 :         if (!isnull && value)
    1901             :         {
    1902             :             /* Found it */
    1903             : 
    1904             :             /* We can now discard any value we had for the temp variable */
    1905          10 :             if (t_var != NULL)
    1906           8 :                 assign_simple_var(estate, t_var, (Datum) 0, true, false);
    1907             : 
    1908             :             /* Evaluate the statement(s), and we're done */
    1909          10 :             return exec_stmts(estate, cwt->stmts);
    1910             :         }
    1911             :     }
    1912             : 
    1913             :     /* We can now discard any value we had for the temp variable */
    1914           5 :     if (t_var != NULL)
    1915           3 :         assign_simple_var(estate, t_var, (Datum) 0, true, false);
    1916             : 
    1917             :     /* SQL2003 mandates this error if there was no ELSE clause */
    1918           5 :     if (!stmt->have_else)
    1919           3 :         ereport(ERROR,
    1920             :                 (errcode(ERRCODE_CASE_NOT_FOUND),
    1921             :                  errmsg("case not found"),
    1922             :                  errhint("CASE statement is missing ELSE part.")));
    1923             : 
    1924             :     /* Evaluate the ELSE statements, and we're done */
    1925           2 :     return exec_stmts(estate, stmt->else_stmts);
    1926             : }
    1927             : 
    1928             : 
    1929             : /* ----------
    1930             :  * exec_stmt_loop           Loop over statements until
    1931             :  *                  an exit occurs.
    1932             :  * ----------
    1933             :  */
    1934             : static int
    1935         102 : exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
    1936             : {
    1937             :     for (;;)
    1938             :     {
    1939         102 :         int         rc = exec_stmts(estate, stmt->body);
    1940             : 
    1941         102 :         switch (rc)
    1942             :         {
    1943             :             case PLPGSQL_RC_OK:
    1944          67 :                 break;
    1945             : 
    1946             :             case PLPGSQL_RC_EXIT:
    1947           8 :                 if (estate->exitlabel == NULL)
    1948           5 :                     return PLPGSQL_RC_OK;
    1949           3 :                 if (stmt->label == NULL)
    1950           2 :                     return PLPGSQL_RC_EXIT;
    1951           1 :                 if (strcmp(stmt->label, estate->exitlabel) != 0)
    1952           0 :                     return PLPGSQL_RC_EXIT;
    1953           1 :                 estate->exitlabel = NULL;
    1954           1 :                 return PLPGSQL_RC_OK;
    1955             : 
    1956             :             case PLPGSQL_RC_CONTINUE:
    1957          27 :                 if (estate->exitlabel == NULL)
    1958             :                     /* anonymous continue, so re-run the loop */
    1959           9 :                     break;
    1960          27 :                 else if (stmt->label != NULL &&
    1961           9 :                          strcmp(stmt->label, estate->exitlabel) == 0)
    1962             :                     /* label matches named continue, so re-run loop */
    1963           9 :                     estate->exitlabel = NULL;
    1964             :                 else
    1965             :                     /* label doesn't match named continue, so propagate upward */
    1966           9 :                     return PLPGSQL_RC_CONTINUE;
    1967           9 :                 break;
    1968             : 
    1969             :             case PLPGSQL_RC_RETURN:
    1970           0 :                 return rc;
    1971             : 
    1972             :             default:
    1973           0 :                 elog(ERROR, "unrecognized rc: %d", rc);
    1974             :         }
    1975          85 :     }
    1976             : }
    1977             : 
    1978             : 
    1979             : /* ----------
    1980             :  * exec_stmt_while          Loop over statements as long
    1981             :  *                  as an expression evaluates to
    1982             :  *                  true or an exit occurs.
    1983             :  * ----------
    1984             :  */
    1985             : static int
    1986          38 : exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
    1987             : {
    1988             :     for (;;)
    1989             :     {
    1990             :         int         rc;
    1991             :         bool        value;
    1992             :         bool        isnull;
    1993             : 
    1994          38 :         value = exec_eval_boolean(estate, stmt->cond, &isnull);
    1995          38 :         exec_eval_cleanup(estate);
    1996             : 
    1997          38 :         if (isnull || !value)
    1998             :             break;
    1999             : 
    2000          31 :         rc = exec_stmts(estate, stmt->body);
    2001             : 
    2002          31 :         switch (rc)
    2003             :         {
    2004             :             case PLPGSQL_RC_OK:
    2005          25 :                 break;
    2006             : 
    2007             :             case PLPGSQL_RC_EXIT:
    2008           0 :                 if (estate->exitlabel == NULL)
    2009           0 :                     return PLPGSQL_RC_OK;
    2010           0 :                 if (stmt->label == NULL)
    2011           0 :                     return PLPGSQL_RC_EXIT;
    2012           0 :                 if (strcmp(stmt->label, estate->exitlabel) != 0)
    2013           0 :                     return PLPGSQL_RC_EXIT;
    2014           0 :                 estate->exitlabel = NULL;
    2015           0 :                 return PLPGSQL_RC_OK;
    2016             : 
    2017             :             case PLPGSQL_RC_CONTINUE:
    2018           6 :                 if (estate->exitlabel == NULL)
    2019             :                     /* anonymous continue, so re-run loop */
    2020           1 :                     break;
    2021          10 :                 else if (stmt->label != NULL &&
    2022           5 :                          strcmp(stmt->label, estate->exitlabel) == 0)
    2023             :                     /* label matches named continue, so re-run loop */
    2024           5 :                     estate->exitlabel = NULL;
    2025             :                 else
    2026             :                     /* label doesn't match named continue, propagate upward */
    2027           0 :                     return PLPGSQL_RC_CONTINUE;
    2028           5 :                 break;
    2029             : 
    2030             :             case PLPGSQL_RC_RETURN:
    2031           0 :                 return rc;
    2032             : 
    2033             :             default:
    2034           0 :                 elog(ERROR, "unrecognized rc: %d", rc);
    2035             :         }
    2036          31 :     }
    2037             : 
    2038           7 :     return PLPGSQL_RC_OK;
    2039             : }
    2040             : 
    2041             : 
    2042             : /* ----------
    2043             :  * exec_stmt_fori           Iterate an integer variable
    2044             :  *                  from a lower to an upper value
    2045             :  *                  incrementing or decrementing by the BY value
    2046             :  * ----------
    2047             :  */
    2048             : static int
    2049          83 : exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
    2050             : {
    2051             :     PLpgSQL_var *var;
    2052             :     Datum       value;
    2053             :     bool        isnull;
    2054             :     Oid         valtype;
    2055             :     int32       valtypmod;
    2056             :     int32       loop_value;
    2057             :     int32       end_value;
    2058             :     int32       step_value;
    2059          83 :     bool        found = false;
    2060          83 :     int         rc = PLPGSQL_RC_OK;
    2061             : 
    2062          83 :     var = (PLpgSQL_var *) (estate->datums[stmt->var->dno]);
    2063             : 
    2064             :     /*
    2065             :      * Get the value of the lower bound
    2066             :      */
    2067          83 :     value = exec_eval_expr(estate, stmt->lower,
    2068             :                            &isnull, &valtype, &valtypmod);
    2069         166 :     value = exec_cast_value(estate, value, &isnull,
    2070             :                             valtype, valtypmod,
    2071          83 :                             var->datatype->typoid,
    2072          83 :                             var->datatype->atttypmod);
    2073          83 :     if (isnull)
    2074           0 :         ereport(ERROR,
    2075             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    2076             :                  errmsg("lower bound of FOR loop cannot be null")));
    2077          83 :     loop_value = DatumGetInt32(value);
    2078          83 :     exec_eval_cleanup(estate);
    2079             : 
    2080             :     /*
    2081             :      * Get the value of the upper bound
    2082             :      */
    2083          83 :     value = exec_eval_expr(estate, stmt->upper,
    2084             :                            &isnull, &valtype, &valtypmod);
    2085         166 :     value = exec_cast_value(estate, value, &isnull,
    2086             :                             valtype, valtypmod,
    2087          83 :                             var->datatype->typoid,
    2088          83 :                             var->datatype->atttypmod);
    2089          83 :     if (isnull)
    2090           0 :         ereport(ERROR,
    2091             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    2092             :                  errmsg("upper bound of FOR loop cannot be null")));
    2093          83 :     end_value = DatumGetInt32(value);
    2094          83 :     exec_eval_cleanup(estate);
    2095             : 
    2096             :     /*
    2097             :      * Get the step value
    2098             :      */
    2099          83 :     if (stmt->step)
    2100             :     {
    2101           0 :         value = exec_eval_expr(estate, stmt->step,
    2102             :                                &isnull, &valtype, &valtypmod);
    2103           0 :         value = exec_cast_value(estate, value, &isnull,
    2104             :                                 valtype, valtypmod,
    2105           0 :                                 var->datatype->typoid,
    2106           0 :                                 var->datatype->atttypmod);
    2107           0 :         if (isnull)
    2108           0 :             ereport(ERROR,
    2109             :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    2110             :                      errmsg("BY value of FOR loop cannot be null")));
    2111           0 :         step_value = DatumGetInt32(value);
    2112           0 :         exec_eval_cleanup(estate);
    2113           0 :         if (step_value <= 0)
    2114           0 :             ereport(ERROR,
    2115             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2116             :                      errmsg("BY value of FOR loop must be greater than zero")));
    2117             :     }
    2118             :     else
    2119          83 :         step_value = 1;
    2120             : 
    2121             :     /*
    2122             :      * Now do the loop
    2123             :      */
    2124             :     for (;;)
    2125             :     {
    2126             :         /*
    2127             :          * Check against upper bound
    2128             :          */
    2129         282 :         if (stmt->reverse)
    2130             :         {
    2131           0 :             if (loop_value < end_value)
    2132           0 :                 break;
    2133             :         }
    2134             :         else
    2135             :         {
    2136         282 :             if (loop_value > end_value)
    2137          80 :                 break;
    2138             :         }
    2139             : 
    2140         202 :         found = true;           /* looped at least once */
    2141             : 
    2142             :         /*
    2143             :          * Assign current value to loop var
    2144             :          */
    2145         202 :         assign_simple_var(estate, var, Int32GetDatum(loop_value), false, false);
    2146             : 
    2147             :         /*
    2148             :          * Execute the statements
    2149             :          */
    2150         202 :         rc = exec_stmts(estate, stmt->body);
    2151             : 
    2152         202 :         if (rc == PLPGSQL_RC_RETURN)
    2153           0 :             break;              /* break out of the loop */
    2154         202 :         else if (rc == PLPGSQL_RC_EXIT)
    2155             :         {
    2156           3 :             if (estate->exitlabel == NULL)
    2157             :                 /* unlabelled exit, finish the current loop */
    2158           1 :                 rc = PLPGSQL_RC_OK;
    2159           4 :             else if (stmt->label != NULL &&
    2160           2 :                      strcmp(stmt->label, estate->exitlabel) == 0)
    2161             :             {
    2162             :                 /* labelled exit, matches the current stmt's label */
    2163           2 :                 estate->exitlabel = NULL;
    2164           2 :                 rc = PLPGSQL_RC_OK;
    2165             :             }
    2166             : 
    2167             :             /*
    2168             :              * otherwise, this is a labelled exit that does not match the
    2169             :              * current statement's label, if any: return RC_EXIT so that the
    2170             :              * EXIT continues to propagate up the stack.
    2171             :              */
    2172           3 :             break;
    2173             :         }
    2174         199 :         else if (rc == PLPGSQL_RC_CONTINUE)
    2175             :         {
    2176           5 :             if (estate->exitlabel == NULL)
    2177             :                 /* unlabelled continue, so re-run the current loop */
    2178           5 :                 rc = PLPGSQL_RC_OK;
    2179           0 :             else if (stmt->label != NULL &&
    2180           0 :                      strcmp(stmt->label, estate->exitlabel) == 0)
    2181             :             {
    2182             :                 /* label matches named continue, so re-run loop */
    2183           0 :                 estate->exitlabel = NULL;
    2184           0 :                 rc = PLPGSQL_RC_OK;
    2185             :             }
    2186             :             else
    2187             :             {
    2188             :                 /*
    2189             :                  * otherwise, this is a named continue that does not match the
    2190             :                  * current statement's label, if any: return RC_CONTINUE so
    2191             :                  * that the CONTINUE will propagate up the stack.
    2192             :                  */
    2193             :                 break;
    2194             :             }
    2195             :         }
    2196             : 
    2197             :         /*
    2198             :          * Increase/decrease loop value, unless it would overflow, in which
    2199             :          * case exit the loop.
    2200             :          */
    2201         199 :         if (stmt->reverse)
    2202             :         {
    2203           0 :             if ((int32) (loop_value - step_value) > loop_value)
    2204           0 :                 break;
    2205           0 :             loop_value -= step_value;
    2206             :         }
    2207             :         else
    2208             :         {
    2209         199 :             if ((int32) (loop_value + step_value) < loop_value)
    2210           0 :                 break;
    2211         199 :             loop_value += step_value;
    2212             :         }
    2213         199 :     }
    2214             : 
    2215             :     /*
    2216             :      * Set the FOUND variable to indicate the result of executing the loop
    2217             :      * (namely, whether we looped one or more times). This must be set here so
    2218             :      * that it does not interfere with the value of the FOUND variable inside
    2219             :      * the loop processing itself.
    2220             :      */
    2221          83 :     exec_set_found(estate, found);
    2222             : 
    2223          83 :     return rc;
    2224             : }
    2225             : 
    2226             : 
    2227             : /* ----------
    2228             :  * exec_stmt_fors           Execute a query, assign each
    2229             :  *                  tuple to a record or row and
    2230             :  *                  execute a group of statements
    2231             :  *                  for it.
    2232             :  * ----------
    2233             :  */
    2234             : static int
    2235         174 : exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
    2236             : {
    2237             :     Portal      portal;
    2238             :     int         rc;
    2239             : 
    2240             :     /*
    2241             :      * Open the implicit cursor for the statement using exec_run_select
    2242             :      */
    2243         174 :     exec_run_select(estate, stmt->query, 0, &portal);
    2244             : 
    2245             :     /*
    2246             :      * Execute the loop
    2247             :      */
    2248         172 :     rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
    2249             : 
    2250             :     /*
    2251             :      * Close the implicit cursor
    2252             :      */
    2253         169 :     SPI_cursor_close(portal);
    2254             : 
    2255         169 :     return rc;
    2256             : }
    2257             : 
    2258             : 
    2259             : /* ----------
    2260             :  * exec_stmt_forc           Execute a loop for each row from a cursor.
    2261             :  * ----------
    2262             :  */
    2263             : static int
    2264           6 : exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
    2265             : {
    2266             :     PLpgSQL_var *curvar;
    2267           6 :     MemoryContext stmt_mcontext = NULL;
    2268           6 :     char       *curname = NULL;
    2269             :     PLpgSQL_expr *query;
    2270             :     ParamListInfo paramLI;
    2271             :     Portal      portal;
    2272             :     int         rc;
    2273             : 
    2274             :     /* ----------
    2275             :      * Get the cursor variable and if it has an assigned name, check
    2276             :      * that it's not in use currently.
    2277             :      * ----------
    2278             :      */
    2279           6 :     curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
    2280           6 :     if (!curvar->isnull)
    2281             :     {
    2282             :         MemoryContext oldcontext;
    2283             : 
    2284             :         /* We only need stmt_mcontext to hold the cursor name string */
    2285           5 :         stmt_mcontext = get_stmt_mcontext(estate);
    2286           5 :         oldcontext = MemoryContextSwitchTo(stmt_mcontext);
    2287           5 :         curname = TextDatumGetCString(curvar->value);
    2288           5 :         MemoryContextSwitchTo(oldcontext);
    2289             : 
    2290           5 :         if (SPI_cursor_find(curname) != NULL)
    2291           0 :             ereport(ERROR,
    2292             :                     (errcode(ERRCODE_DUPLICATE_CURSOR),
    2293             :                      errmsg("cursor \"%s\" already in use", curname)));
    2294             :     }
    2295             : 
    2296             :     /* ----------
    2297             :      * Open the cursor just like an OPEN command
    2298             :      *
    2299             :      * Note: parser should already have checked that statement supplies
    2300             :      * args iff cursor needs them, but we check again to be safe.
    2301             :      * ----------
    2302             :      */
    2303           6 :     if (stmt->argquery != NULL)
    2304             :     {
    2305             :         /* ----------
    2306             :          * OPEN CURSOR with args.  We fake a SELECT ... INTO ...
    2307             :          * statement to evaluate the args and put 'em into the
    2308             :          * internal row.
    2309             :          * ----------
    2310             :          */
    2311             :         PLpgSQL_stmt_execsql set_args;
    2312             : 
    2313           2 :         if (curvar->cursor_explicit_argrow < 0)
    2314           0 :             ereport(ERROR,
    2315             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2316             :                      errmsg("arguments given for cursor without arguments")));
    2317             : 
    2318           2 :         memset(&set_args, 0, sizeof(set_args));
    2319           2 :         set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
    2320           2 :         set_args.lineno = stmt->lineno;
    2321           2 :         set_args.sqlstmt = stmt->argquery;
    2322           2 :         set_args.into = true;
    2323             :         /* XXX historically this has not been STRICT */
    2324           2 :         set_args.row = (PLpgSQL_row *)
    2325           2 :             (estate->datums[curvar->cursor_explicit_argrow]);
    2326             : 
    2327           2 :         if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
    2328           0 :             elog(ERROR, "open cursor failed during argument processing");
    2329             :     }
    2330             :     else
    2331             :     {
    2332           4 :         if (curvar->cursor_explicit_argrow >= 0)
    2333           0 :             ereport(ERROR,
    2334             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2335             :                      errmsg("arguments required for cursor")));
    2336             :     }
    2337             : 
    2338           6 :     query = curvar->cursor_explicit_expr;
    2339           6 :     Assert(query);
    2340             : 
    2341           6 :     if (query->plan == NULL)
    2342           3 :         exec_prepare_plan(estate, query, curvar->cursor_options);
    2343             : 
    2344             :     /*
    2345             :      * Set up short-lived ParamListInfo
    2346             :      */
    2347           6 :     paramLI = setup_unshared_param_list(estate, query);
    2348             : 
    2349             :     /*
    2350             :      * Open the cursor (the paramlist will get copied into the portal)
    2351             :      */
    2352           6 :     portal = SPI_cursor_open_with_paramlist(curname, query->plan,
    2353             :                                             paramLI,
    2354           6 :                                             estate->readonly_func);
    2355           6 :     if (portal == NULL)
    2356           0 :         elog(ERROR, "could not open cursor: %s",
    2357             :              SPI_result_code_string(SPI_result));
    2358             : 
    2359             :     /*
    2360             :      * If cursor variable was NULL, store the generated portal name in it
    2361             :      */
    2362           6 :     if (curname == NULL)
    2363           1 :         assign_text_var(estate, curvar, portal->name);
    2364             : 
    2365             :     /*
    2366             :      * Clean up before entering exec_for_query
    2367             :      */
    2368           6 :     exec_eval_cleanup(estate);
    2369           6 :     if (stmt_mcontext)
    2370           5 :         MemoryContextReset(stmt_mcontext);
    2371             : 
    2372             :     /*
    2373             :      * Execute the loop.  We can't prefetch because the cursor is accessible
    2374             :      * to the user, for instance via UPDATE WHERE CURRENT OF within the loop.
    2375             :      */
    2376           6 :     rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, false);
    2377             : 
    2378             :     /* ----------
    2379             :      * Close portal, and restore cursor variable if it was initially NULL.
    2380             :      * ----------
    2381             :      */
    2382           6 :     SPI_cursor_close(portal);
    2383             : 
    2384           6 :     if (curname == NULL)
    2385           1 :         assign_simple_var(estate, curvar, (Datum) 0, true, false);
    2386             : 
    2387           6 :     return rc;
    2388             : }
    2389             : 
    2390             : 
    2391             : /* ----------
    2392             :  * exec_stmt_foreach_a          Loop over elements or slices of an array
    2393             :  *
    2394             :  * When looping over elements, the loop variable is the same type that the
    2395             :  * array stores (eg: integer), when looping through slices, the loop variable
    2396             :  * is an array of size and dimensions to match the size of the slice.
    2397             :  * ----------
    2398             :  */
    2399             : static int
    2400          15 : exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
    2401             : {
    2402             :     ArrayType  *arr;
    2403             :     Oid         arrtype;
    2404             :     int32       arrtypmod;
    2405             :     PLpgSQL_datum *loop_var;
    2406             :     Oid         loop_var_elem_type;
    2407          15 :     bool        found = false;
    2408          15 :     int         rc = PLPGSQL_RC_OK;
    2409             :     MemoryContext stmt_mcontext;
    2410             :     MemoryContext oldcontext;
    2411             :     ArrayIterator array_iterator;
    2412             :     Oid         iterator_result_type;
    2413             :     int32       iterator_result_typmod;
    2414             :     Datum       value;
    2415             :     bool        isnull;
    2416             : 
    2417             :     /* get the value of the array expression */
    2418          15 :     value = exec_eval_expr(estate, stmt->expr, &isnull, &arrtype, &arrtypmod);
    2419          15 :     if (isnull)
    2420           0 :         ereport(ERROR,
    2421             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    2422             :                  errmsg("FOREACH expression must not be null")));
    2423             : 
    2424             :     /*
    2425             :      * Do as much as possible of the code below in stmt_mcontext, to avoid any
    2426             :      * leaks from called subroutines.  We need a private stmt_mcontext since
    2427             :      * we'll be calling arbitrary statement code.
    2428             :      */
    2429          15 :     stmt_mcontext = get_stmt_mcontext(estate);
    2430          15 :     push_stmt_mcontext(estate);
    2431          15 :     oldcontext = MemoryContextSwitchTo(stmt_mcontext);
    2432             : 
    2433             :     /* check the type of the expression - must be an array */
    2434          15 :     if (!OidIsValid(get_element_type(arrtype)))
    2435           0 :         ereport(ERROR,
    2436             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2437             :                  errmsg("FOREACH expression must yield an array, not type %s",
    2438             :                         format_type_be(arrtype))));
    2439             : 
    2440             :     /*
    2441             :      * We must copy the array into stmt_mcontext, else it will disappear in
    2442             :      * exec_eval_cleanup.  This is annoying, but cleanup will certainly happen
    2443             :      * while running the loop body, so we have little choice.
    2444             :      */
    2445          15 :     arr = DatumGetArrayTypePCopy(value);
    2446             : 
    2447             :     /* Clean up any leftover temporary memory */
    2448          15 :     exec_eval_cleanup(estate);
    2449             : 
    2450             :     /* Slice dimension must be less than or equal to array dimension */
    2451          15 :     if (stmt->slice < 0 || stmt->slice > ARR_NDIM(arr))
    2452           1 :         ereport(ERROR,
    2453             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    2454             :                  errmsg("slice dimension (%d) is out of the valid range 0..%d",
    2455             :                         stmt->slice, ARR_NDIM(arr))));
    2456             : 
    2457             :     /* Set up the loop variable and see if it is of an array type */
    2458          14 :     loop_var = estate->datums[stmt->varno];
    2459          26 :     if (loop_var->dtype == PLPGSQL_DTYPE_REC ||
    2460          12 :         loop_var->dtype == PLPGSQL_DTYPE_ROW)
    2461             :     {
    2462             :         /*
    2463             :          * Record/row variable is certainly not of array type, and might not
    2464             :          * be initialized at all yet, so don't try to get its type
    2465             :          */
    2466           4 :         loop_var_elem_type = InvalidOid;
    2467             :     }
    2468             :     else
    2469          10 :         loop_var_elem_type = get_element_type(plpgsql_exec_get_datum_type(estate,
    2470             :                                                                           loop_var));
    2471             : 
    2472             :     /*
    2473             :      * Sanity-check the loop variable type.  We don't try very hard here, and
    2474             :      * should not be too picky since it's possible that exec_assign_value can
    2475             :      * coerce values of different types.  But it seems worthwhile to complain
    2476             :      * if the array-ness of the loop variable is not right.
    2477             :      */
    2478          14 :     if (stmt->slice > 0 && loop_var_elem_type == InvalidOid)
    2479           2 :         ereport(ERROR,
    2480             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2481             :                  errmsg("FOREACH ... SLICE loop variable must be of an array type")));
    2482          12 :     if (stmt->slice == 0 && loop_var_elem_type != InvalidOid)
    2483           0 :         ereport(ERROR,
    2484             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2485             :                  errmsg("FOREACH loop variable must not be of an array type")));
    2486             : 
    2487             :     /* Create an iterator to step through the array */
    2488          12 :     array_iterator = array_create_iterator(arr, stmt->slice, NULL);
    2489             : 
    2490             :     /* Identify iterator result type */
    2491          12 :     if (stmt->slice > 0)
    2492             :     {
    2493             :         /* When slicing, nominal type of result is same as array type */
    2494           6 :         iterator_result_type = arrtype;
    2495           6 :         iterator_result_typmod = arrtypmod;
    2496             :     }
    2497             :     else
    2498             :     {
    2499             :         /* Without slicing, results are individual array elements */
    2500           6 :         iterator_result_type = ARR_ELEMTYPE(arr);
    2501           6 :         iterator_result_typmod = arrtypmod;
    2502             :     }
    2503             : 
    2504             :     /* Iterate over the array elements or slices */
    2505          55 :     while (array_iterate(array_iterator, &value, &isnull))
    2506             :     {
    2507          31 :         found = true;           /* looped at least once */
    2508             : 
    2509             :         /* exec_assign_value and exec_stmts must run in the main context */
    2510          31 :         MemoryContextSwitchTo(oldcontext);
    2511             : 
    2512             :         /* Assign current element/slice to the loop variable */
    2513          31 :         exec_assign_value(estate, loop_var, value, isnull,
    2514             :                           iterator_result_type, iterator_result_typmod);
    2515             : 
    2516             :         /* In slice case, value is temporary; must free it to avoid leakage */
    2517          31 :         if (stmt->slice > 0)
    2518           9 :             pfree(DatumGetPointer(value));
    2519             : 
    2520             :         /*
    2521             :          * Execute the statements
    2522             :          */
    2523          31 :         rc = exec_stmts(estate, stmt->body);
    2524             : 
    2525             :         /* Handle the return code */
    2526          31 :         if (rc == PLPGSQL_RC_RETURN)
    2527           0 :             break;              /* break out of the loop */
    2528          31 :         else if (rc == PLPGSQL_RC_EXIT)
    2529             :         {
    2530           0 :             if (estate->exitlabel == NULL)
    2531             :                 /* unlabelled exit, finish the current loop */
    2532           0 :                 rc = PLPGSQL_RC_OK;
    2533           0 :             else if (stmt->label != NULL &&
    2534           0 :                      strcmp(stmt->label, estate->exitlabel) == 0)
    2535             :             {
    2536             :                 /* labelled exit, matches the current stmt's label */
    2537           0 :                 estate->exitlabel = NULL;
    2538           0 :                 rc = PLPGSQL_RC_OK;
    2539             :             }
    2540             : 
    2541             :             /*
    2542             :              * otherwise, this is a labelled exit that does not match the
    2543             :              * current statement's label, if any: return RC_EXIT so that the
    2544             :              * EXIT continues to propagate up the stack.
    2545             :              */
    2546           0 :             break;
    2547             :         }
    2548          31 :         else if (rc == PLPGSQL_RC_CONTINUE)
    2549             :         {
    2550           0 :             if (estate->exitlabel == NULL)
    2551             :                 /* unlabelled continue, so re-run the current loop */
    2552           0 :                 rc = PLPGSQL_RC_OK;
    2553           0 :             else if (stmt->label != NULL &&
    2554           0 :                      strcmp(stmt->label, estate->exitlabel) == 0)
    2555             :             {
    2556             :                 /* label matches named continue, so re-run loop */
    2557           0 :                 estate->exitlabel = NULL;
    2558           0 :                 rc = PLPGSQL_RC_OK;
    2559             :             }
    2560             :             else
    2561             :             {
    2562             :                 /*
    2563             :                  * otherwise, this is a named continue that does not match the
    2564             :                  * current statement's label, if any: return RC_CONTINUE so
    2565             :                  * that the CONTINUE will propagate up the stack.
    2566             :                  */
    2567             :                 break;
    2568             :             }
    2569             :         }
    2570             : 
    2571          31 :         MemoryContextSwitchTo(stmt_mcontext);
    2572             :     }
    2573             : 
    2574             :     /* Restore memory context state */
    2575          12 :     MemoryContextSwitchTo(oldcontext);
    2576          12 :     pop_stmt_mcontext(estate);
    2577             : 
    2578             :     /* Release temporary memory, including the array value */
    2579          12 :     MemoryContextReset(stmt_mcontext);
    2580             : 
    2581             :     /*
    2582             :      * Set the FOUND variable to indicate the result of executing the loop
    2583             :      * (namely, whether we looped one or more times). This must be set here so
    2584             :      * that it does not interfere with the value of the FOUND variable inside
    2585             :      * the loop processing itself.
    2586             :      */
    2587          12 :     exec_set_found(estate, found);
    2588             : 
    2589          12 :     return rc;
    2590             : }
    2591             : 
    2592             : 
    2593             : /* ----------
    2594             :  * exec_stmt_exit           Implements EXIT and CONTINUE
    2595             :  *
    2596             :  * This begins the process of exiting / restarting a loop.
    2597             :  * ----------
    2598             :  */
    2599             : static int
    2600         190 : exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
    2601             : {
    2602             :     /*
    2603             :      * If the exit / continue has a condition, evaluate it
    2604             :      */
    2605         190 :     if (stmt->cond != NULL)
    2606             :     {
    2607             :         bool        value;
    2608             :         bool        isnull;
    2609             : 
    2610         165 :         value = exec_eval_boolean(estate, stmt->cond, &isnull);
    2611         165 :         exec_eval_cleanup(estate);
    2612         165 :         if (isnull || value == false)
    2613         113 :             return PLPGSQL_RC_OK;
    2614             :     }
    2615             : 
    2616          77 :     estate->exitlabel = stmt->label;
    2617          77 :     if (stmt->is_exit)
    2618          10 :         return PLPGSQL_RC_EXIT;
    2619             :     else
    2620          67 :         return PLPGSQL_RC_CONTINUE;
    2621             : }
    2622             : 
    2623             : 
    2624             : /* ----------
    2625             :  * exec_stmt_return         Evaluate an expression and start
    2626             :  *                  returning from the function.
    2627             :  *
    2628             :  * Note: in the retistuple code paths, the returned tuple is always in the
    2629             :  * function's main context, whereas for non-tuple data types the result may
    2630             :  * be in the eval_mcontext.  The former case is not a memory leak since we're
    2631             :  * about to exit the function anyway.  (If you want to change it, note that
    2632             :  * exec_stmt_block() knows about this behavior.)  The latter case means that
    2633             :  * we must not do exec_eval_cleanup while unwinding the control stack.
    2634             :  * ----------
    2635             :  */
    2636             : static int
    2637       12221 : exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
    2638             : {
    2639             :     /*
    2640             :      * If processing a set-returning PL/pgSQL function, the final RETURN
    2641             :      * indicates that the function is finished producing tuples.  The rest of
    2642             :      * the work will be done at the top level.
    2643             :      */
    2644       12221 :     if (estate->retisset)
    2645          77 :         return PLPGSQL_RC_RETURN;
    2646             : 
    2647             :     /* initialize for null result (possibly a tuple) */
    2648       12144 :     estate->retval = (Datum) 0;
    2649       12144 :     estate->rettupdesc = NULL;
    2650       12144 :     estate->retisnull = true;
    2651       12144 :     estate->rettype = InvalidOid;
    2652             : 
    2653             :     /*
    2654             :      * Special case path when the RETURN expression is a simple variable
    2655             :      * reference; in particular, this path is always taken in functions with
    2656             :      * one or more OUT parameters.
    2657             :      *
    2658             :      * This special case is especially efficient for returning variables that
    2659             :      * have R/W expanded values: we can put the R/W pointer directly into
    2660             :      * estate->retval, leading to transferring the value to the caller's
    2661             :      * context cheaply.  If we went through exec_eval_expr we'd end up with a
    2662             :      * R/O pointer.  It's okay to skip MakeExpandedObjectReadOnly here since
    2663             :      * we know we won't need the variable's value within the function anymore.
    2664             :      */
    2665       12144 :     if (stmt->retvarno >= 0)
    2666             :     {
    2667        5778 :         PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
    2668             : 
    2669        5778 :         switch (retvar->dtype)
    2670             :         {
    2671             :             case PLPGSQL_DTYPE_VAR:
    2672             :                 {
    2673        4129 :                     PLpgSQL_var *var = (PLpgSQL_var *) retvar;
    2674             : 
    2675        4129 :                     estate->retval = var->value;
    2676        4129 :                     estate->retisnull = var->isnull;
    2677        4129 :                     estate->rettype = var->datatype->typoid;
    2678             : 
    2679             :                     /*
    2680             :                      * Cope with retistuple case.  A PLpgSQL_var could not be
    2681             :                      * of composite type, so we needn't make any effort to
    2682             :                      * convert.  However, for consistency with the expression
    2683             :                      * code path, don't throw error if the result is NULL.
    2684             :                      */
    2685        4129 :                     if (estate->retistuple && !estate->retisnull)
    2686           1 :                         ereport(ERROR,
    2687             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2688             :                                  errmsg("cannot return non-composite value from function returning composite type")));
    2689             :                 }
    2690        4128 :                 break;
    2691             : 
    2692             :             case PLPGSQL_DTYPE_REC:
    2693             :                 {
    2694        1610 :                     PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
    2695             :                     int32       rettypmod;
    2696             : 
    2697        1610 :                     if (HeapTupleIsValid(rec->tup))
    2698             :                     {
    2699        1601 :                         if (estate->retistuple)
    2700             :                         {
    2701        1601 :                             estate->retval = PointerGetDatum(rec->tup);
    2702        1601 :                             estate->rettupdesc = rec->tupdesc;
    2703        1601 :                             estate->retisnull = false;
    2704             :                         }
    2705             :                         else
    2706           0 :                             exec_eval_datum(estate,
    2707             :                                             retvar,
    2708             :                                             &estate->rettype,
    2709             :                                             &rettypmod,
    2710             :                                             &estate->retval,
    2711             :                                             &estate->retisnull);
    2712             :                     }
    2713             :                 }
    2714        1610 :                 break;
    2715             : 
    2716             :             case PLPGSQL_DTYPE_ROW:
    2717             :                 {
    2718          39 :                     PLpgSQL_row *row = (PLpgSQL_row *) retvar;
    2719             :                     int32       rettypmod;
    2720             : 
    2721          39 :                     if (estate->retistuple)
    2722             :                     {
    2723             :                         HeapTuple   tup;
    2724             : 
    2725          38 :                         if (!row->rowtupdesc)    /* should not happen */
    2726           0 :                             elog(ERROR, "row variable has no tupdesc");
    2727          38 :                         tup = make_tuple_from_row(estate, row, row->rowtupdesc);
    2728          38 :                         if (tup == NULL)    /* should not happen */
    2729           0 :                             elog(ERROR, "row not compatible with its own tupdesc");
    2730          38 :                         estate->retval = PointerGetDatum(tup);
    2731          38 :                         estate->rettupdesc = row->rowtupdesc;
    2732          38 :                         estate->retisnull = false;
    2733             :                     }
    2734             :                     else
    2735           1 :                         exec_eval_datum(estate,
    2736             :                                         retvar,
    2737             :                                         &estate->rettype,
    2738             :                                         &rettypmod,
    2739             :                                         &estate->retval,
    2740             :                                         &estate->retisnull);
    2741             :                 }
    2742          39 :                 break;
    2743             : 
    2744             :             default:
    2745           0 :                 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
    2746             :         }
    2747             : 
    2748        5777 :         return PLPGSQL_RC_RETURN;
    2749             :     }
    2750             : 
    2751        6366 :     if (stmt->expr != NULL)
    2752             :     {
    2753             :         int32       rettypmod;
    2754             : 
    2755        6263 :         estate->retval = exec_eval_expr(estate, stmt->expr,
    2756             :                                         &(estate->retisnull),
    2757             :                                         &(estate->rettype),
    2758             :                                         &rettypmod);
    2759             : 
    2760        6257 :         if (estate->retistuple && !estate->retisnull)
    2761             :         {
    2762             :             /* Convert composite datum to a HeapTuple and TupleDesc */
    2763             :             HeapTuple   tuple;
    2764             :             TupleDesc   tupdesc;
    2765             : 
    2766             :             /* Source must be of RECORD or composite type */
    2767          10 :             if (!type_is_rowtype(estate->rettype))
    2768           1 :                 ereport(ERROR,
    2769             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    2770             :                          errmsg("cannot return non-composite value from function returning composite type")));
    2771           9 :             tuple = get_tuple_from_datum(estate->retval);
    2772           9 :             tupdesc = get_tupdesc_from_datum(estate->retval);
    2773           9 :             estate->retval = PointerGetDatum(tuple);
    2774           9 :             estate->rettupdesc = CreateTupleDescCopy(tupdesc);
    2775           9 :             ReleaseTupleDesc(tupdesc);
    2776             :         }
    2777             : 
    2778        6256 :         return PLPGSQL_RC_RETURN;
    2779             :     }
    2780             : 
    2781             :     /*
    2782             :      * Special hack for function returning VOID: instead of NULL, return a
    2783             :      * non-null VOID value.  This is of dubious importance but is kept for
    2784             :      * backwards compatibility.
    2785             :      */
    2786         103 :     if (estate->fn_rettype == VOIDOID)
    2787             :     {
    2788         103 :         estate->retval = (Datum) 0;
    2789         103 :         estate->retisnull = false;
    2790         103 :         estate->rettype = VOIDOID;
    2791             :     }
    2792             : 
    2793         103 :     return PLPGSQL_RC_RETURN;
    2794             : }
    2795             : 
    2796             : /* ----------
    2797             :  * exec_stmt_return_next        Evaluate an expression and add it to the
    2798             :  *                              list of tuples returned by the current
    2799             :  *                              SRF.
    2800             :  * ----------
    2801             :  */
    2802             : static int
    2803         156 : exec_stmt_return_next(PLpgSQL_execstate *estate,
    2804             :                       PLpgSQL_stmt_return_next *stmt)
    2805             : {
    2806             :     TupleDesc   tupdesc;
    2807             :     int         natts;
    2808             :     HeapTuple   tuple;
    2809             :     MemoryContext oldcontext;
    2810             : 
    2811         156 :     if (!estate->retisset)
    2812           0 :         ereport(ERROR,
    2813             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2814             :                  errmsg("cannot use RETURN NEXT in a non-SETOF function")));
    2815             : 
    2816         156 :     if (estate->tuple_store == NULL)
    2817          58 :         exec_init_tuple_store(estate);
    2818             : 
    2819             :     /* rettupdesc will be filled by exec_init_tuple_store */
    2820         156 :     tupdesc = estate->rettupdesc;
    2821         156 :     natts = tupdesc->natts;
    2822             : 
    2823             :     /*
    2824             :      * Special case path when the RETURN NEXT expression is a simple variable
    2825             :      * reference; in particular, this path is always taken in functions with
    2826             :      * one or more OUT parameters.
    2827             :      *
    2828             :      * Unlike exec_statement_return, there's no special win here for R/W
    2829             :      * expanded values, since they'll have to get flattened to go into the
    2830             :      * tuplestore.  Indeed, we'd better make them R/O to avoid any risk of the
    2831             :      * casting step changing them in-place.
    2832             :      */
    2833         156 :     if (stmt->retvarno >= 0)
    2834             :     {
    2835          66 :         PLpgSQL_datum *retvar = estate->datums[stmt->retvarno];
    2836             : 
    2837          66 :         switch (retvar->dtype)
    2838             :         {
    2839             :             case PLPGSQL_DTYPE_VAR:
    2840             :                 {
    2841          29 :                     PLpgSQL_var *var = (PLpgSQL_var *) retvar;
    2842          29 :                     Datum       retval = var->value;
    2843          29 :                     bool        isNull = var->isnull;
    2844          29 :                     Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
    2845             : 
    2846          29 :                     if (natts != 1)
    2847           0 :                         ereport(ERROR,
    2848             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2849             :                                  errmsg("wrong result type supplied in RETURN NEXT")));
    2850             : 
    2851             :                     /* let's be very paranoid about the cast step */
    2852          29 :                     retval = MakeExpandedObjectReadOnly(retval,
    2853             :                                                         isNull,
    2854             :                                                         var->datatype->typlen);
    2855             : 
    2856             :                     /* coerce type if needed */
    2857          87 :                     retval = exec_cast_value(estate,
    2858             :                                              retval,
    2859             :                                              &isNull,
    2860          29 :                                              var->datatype->typoid,
    2861          29 :                                              var->datatype->atttypmod,
    2862             :                                              attr->atttypid,
    2863             :                                              attr->atttypmod);
    2864             : 
    2865          29 :                     tuplestore_putvalues(estate->tuple_store, tupdesc,
    2866             :                                          &retval, &isNull);
    2867             :                 }
    2868          29 :                 break;
    2869             : 
    2870             :             case PLPGSQL_DTYPE_REC:
    2871             :                 {
    2872          25 :                     PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
    2873             :                     TupleConversionMap *tupmap;
    2874             : 
    2875          25 :                     if (!HeapTupleIsValid(rec->tup))
    2876           0 :                         ereport(ERROR,
    2877             :                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    2878             :                                  errmsg("record \"%s\" is not assigned yet",
    2879             :                                         rec->refname),
    2880             :                                  errdetail("The tuple structure of a not-yet-assigned"
    2881             :                                            " record is indeterminate.")));
    2882             : 
    2883             :                     /* Use eval_mcontext for tuple conversion work */
    2884          25 :                     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    2885          25 :                     tupmap = convert_tuples_by_position(rec->tupdesc,
    2886             :                                                         tupdesc,
    2887             :                                                         gettext_noop("wrong record type supplied in RETURN NEXT"));
    2888          25 :                     tuple = rec->tup;
    2889          25 :                     if (tupmap)
    2890           5 :                         tuple = do_convert_tuple(tuple, tupmap);
    2891          25 :                     tuplestore_puttuple(estate->tuple_store, tuple);
    2892          25 :                     MemoryContextSwitchTo(oldcontext);
    2893             :                 }
    2894          25 :                 break;
    2895             : 
    2896             :             case PLPGSQL_DTYPE_ROW:
    2897             :                 {
    2898          12 :                     PLpgSQL_row *row = (PLpgSQL_row *) retvar;
    2899             : 
    2900             :                     /* Use eval_mcontext for tuple conversion work */
    2901          12 :                     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    2902          12 :                     tuple = make_tuple_from_row(estate, row, tupdesc);
    2903          12 :                     if (tuple == NULL)
    2904           0 :                         ereport(ERROR,
    2905             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    2906             :                                  errmsg("wrong record type supplied in RETURN NEXT")));
    2907          12 :                     tuplestore_puttuple(estate->tuple_store, tuple);
    2908          12 :                     MemoryContextSwitchTo(oldcontext);
    2909             :                 }
    2910          12 :                 break;
    2911             : 
    2912             :             default:
    2913           0 :                 elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
    2914             :                 break;
    2915             :         }
    2916             :     }
    2917          90 :     else if (stmt->expr)
    2918             :     {
    2919             :         Datum       retval;
    2920             :         bool        isNull;
    2921             :         Oid         rettype;
    2922             :         int32       rettypmod;
    2923             : 
    2924          90 :         retval = exec_eval_expr(estate,
    2925             :                                 stmt->expr,
    2926             :                                 &isNull,
    2927             :                                 &rettype,
    2928             :                                 &rettypmod);
    2929             : 
    2930          90 :         if (estate->retistuple)
    2931             :         {
    2932             :             /* Expression should be of RECORD or composite type */
    2933          80 :             if (!isNull)
    2934             :             {
    2935             :                 TupleDesc   retvaldesc;
    2936             :                 TupleConversionMap *tupmap;
    2937             : 
    2938          79 :                 if (!type_is_rowtype(rettype))
    2939           0 :                     ereport(ERROR,
    2940             :                             (errcode(ERRCODE_DATATYPE_MISMATCH),
    2941             :                              errmsg("cannot return non-composite value from function returning composite type")));
    2942             : 
    2943             :                 /* Use eval_mcontext for tuple conversion work */
    2944          79 :                 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    2945          79 :                 tuple = get_tuple_from_datum(retval);
    2946          79 :                 retvaldesc = get_tupdesc_from_datum(retval);
    2947          79 :                 tupmap = convert_tuples_by_position(retvaldesc, tupdesc,
    2948             :                                                     gettext_noop("returned record type does not match expected record type"));
    2949          79 :                 if (tupmap)
    2950           0 :                     tuple = do_convert_tuple(tuple, tupmap);
    2951          79 :                 tuplestore_puttuple(estate->tuple_store, tuple);
    2952          79 :                 ReleaseTupleDesc(retvaldesc);
    2953          79 :                 MemoryContextSwitchTo(oldcontext);
    2954             :             }
    2955             :             else
    2956             :             {
    2957             :                 /* Composite NULL --- store a row of nulls */
    2958             :                 Datum      *nulldatums;
    2959             :                 bool       *nullflags;
    2960             : 
    2961           1 :                 nulldatums = (Datum *)
    2962           1 :                     eval_mcontext_alloc0(estate, natts * sizeof(Datum));
    2963           1 :                 nullflags = (bool *)
    2964           1 :                     eval_mcontext_alloc(estate, natts * sizeof(bool));
    2965           1 :                 memset(nullflags, true, natts * sizeof(bool));
    2966           1 :                 tuplestore_putvalues(estate->tuple_store, tupdesc,
    2967             :                                      nulldatums, nullflags);
    2968             :             }
    2969             :         }
    2970             :         else
    2971             :         {
    2972          10 :             Form_pg_attribute attr = TupleDescAttr(tupdesc, 0);
    2973             : 
    2974             :             /* Simple scalar result */
    2975          10 :             if (natts != 1)
    2976           0 :                 ereport(ERROR,
    2977             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    2978             :                          errmsg("wrong result type supplied in RETURN NEXT")));
    2979             : 
    2980             :             /* coerce type if needed */
    2981          10 :             retval = exec_cast_value(estate,
    2982             :                                      retval,
    2983             :                                      &isNull,
    2984             :                                      rettype,
    2985             :                                      rettypmod,
    2986             :                                      attr->atttypid,
    2987             :                                      attr->atttypmod);
    2988             : 
    2989          10 :             tuplestore_putvalues(estate->tuple_store, tupdesc,
    2990             :                                  &retval, &isNull);
    2991             :         }
    2992             :     }
    2993             :     else
    2994             :     {
    2995           0 :         ereport(ERROR,
    2996             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2997             :                  errmsg("RETURN NEXT must have a parameter")));
    2998             :     }
    2999             : 
    3000         156 :     exec_eval_cleanup(estate);
    3001             : 
    3002         156 :     return PLPGSQL_RC_OK;
    3003             : }
    3004             : 
    3005             : /* ----------
    3006             :  * exec_stmt_return_query       Evaluate a query and add it to the
    3007             :  *                              list of tuples returned by the current
    3008             :  *                              SRF.
    3009             :  * ----------
    3010             :  */
    3011             : static int
    3012          25 : exec_stmt_return_query(PLpgSQL_execstate *estate,
    3013             :                        PLpgSQL_stmt_return_query *stmt)
    3014             : {
    3015             :     Portal      portal;
    3016          25 :     uint64      processed = 0;
    3017             :     TupleConversionMap *tupmap;
    3018             :     MemoryContext oldcontext;
    3019             : 
    3020          25 :     if (!estate->retisset)
    3021           0 :         ereport(ERROR,
    3022             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    3023             :                  errmsg("cannot use RETURN QUERY in a non-SETOF function")));
    3024             : 
    3025          25 :     if (estate->tuple_store == NULL)
    3026          16 :         exec_init_tuple_store(estate);
    3027             : 
    3028          25 :     if (stmt->query != NULL)
    3029             :     {
    3030             :         /* static query */
    3031          17 :         exec_run_select(estate, stmt->query, 0, &portal);
    3032             :     }
    3033             :     else
    3034             :     {
    3035             :         /* RETURN QUERY EXECUTE */
    3036           8 :         Assert(stmt->dynquery != NULL);
    3037           8 :         portal = exec_dynquery_with_params(estate, stmt->dynquery,
    3038             :                                            stmt->params, NULL,
    3039             :                                            0);
    3040             :     }
    3041             : 
    3042             :     /* Use eval_mcontext for tuple conversion work */
    3043          25 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    3044             : 
    3045          25 :     tupmap = convert_tuples_by_position(portal->tupDesc,
    3046             :                                         estate->rettupdesc,
    3047             :                                         gettext_noop("structure of query does not match function result type"));
    3048             : 
    3049             :     while (true)
    3050             :     {
    3051             :         uint64      i;
    3052             : 
    3053          48 :         SPI_cursor_fetch(portal, true, 50);
    3054             : 
    3055             :         /* SPI will have changed CurrentMemoryContext */
    3056          48 :         MemoryContextSwitchTo(get_eval_mcontext(estate));
    3057             : 
    3058          48 :         if (SPI_processed == 0)
    3059          25 :             break;
    3060             : 
    3061          96 :         for (i = 0; i < SPI_processed; i++)
    3062             :         {
    3063          73 :             HeapTuple   tuple = SPI_tuptable->vals[i];
    3064             : 
    3065          73 :             if (tupmap)
    3066          12 :                 tuple = do_convert_tuple(tuple, tupmap);
    3067          73 :             tuplestore_puttuple(estate->tuple_store, tuple);
    3068          73 :             if (tupmap)
    3069          12 :                 heap_freetuple(tuple);
    3070          73 :             processed++;
    3071             :         }
    3072             : 
    3073          23 :         SPI_freetuptable(SPI_tuptable);
    3074          23 :     }
    3075             : 
    3076          25 :     SPI_freetuptable(SPI_tuptable);
    3077          25 :     SPI_cursor_close(portal);
    3078             : 
    3079          25 :     MemoryContextSwitchTo(oldcontext);
    3080          25 :     exec_eval_cleanup(estate);
    3081             : 
    3082          25 :     estate->eval_processed = processed;
    3083          25 :     exec_set_found(estate, processed != 0);
    3084             : 
    3085          25 :     return PLPGSQL_RC_OK;
    3086             : }
    3087             : 
    3088             : static void
    3089          74 : exec_init_tuple_store(PLpgSQL_execstate *estate)
    3090             : {
    3091          74 :     ReturnSetInfo *rsi = estate->rsi;
    3092             :     MemoryContext oldcxt;
    3093             :     ResourceOwner oldowner;
    3094             : 
    3095             :     /*
    3096             :      * Check caller can handle a set result in the way we want
    3097             :      */
    3098         148 :     if (!rsi || !IsA(rsi, ReturnSetInfo) ||
    3099         148 :         (rsi->allowedModes & SFRM_Materialize) == 0 ||
    3100          74 :         rsi->expectedDesc == NULL)
    3101           0 :         ereport(ERROR,
    3102             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3103             :                  errmsg("set-valued function called in context that cannot accept a set")));
    3104             : 
    3105             :     /*
    3106             :      * Switch to the right memory context and resource owner for storing the
    3107             :      * tuplestore for return set. If we're within a subtransaction opened for
    3108             :      * an exception-block, for example, we must still create the tuplestore in
    3109             :      * the resource owner that was active when this function was entered, and
    3110             :      * not in the subtransaction resource owner.
    3111             :      */
    3112          74 :     oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
    3113          74 :     oldowner = CurrentResourceOwner;
    3114          74 :     CurrentResourceOwner = estate->tuple_store_owner;
    3115             : 
    3116          74 :     estate->tuple_store =
    3117          74 :         tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
    3118             :                               false, work_mem);
    3119             : 
    3120          74 :     CurrentResourceOwner = oldowner;
    3121          74 :     MemoryContextSwitchTo(oldcxt);
    3122             : 
    3123          74 :     estate->rettupdesc = rsi->expectedDesc;
    3124          74 : }
    3125             : 
    3126             : #define SET_RAISE_OPTION_TEXT(opt, name) \
    3127             : do { \
    3128             :     if (opt) \
    3129             :         ereport(ERROR, \
    3130             :                 (errcode(ERRCODE_SYNTAX_ERROR), \
    3131             :                  errmsg("RAISE option already specified: %s", \
    3132             :                         name))); \
    3133             :     opt = MemoryContextStrdup(stmt_mcontext, extval); \
    3134             : } while (0)
    3135             : 
    3136             : /* ----------
    3137             :  * exec_stmt_raise          Build a message and throw it with elog()
    3138             :  * ----------
    3139             :  */
    3140             : static int
    3141        1334 : exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
    3142             : {
    3143        1334 :     int         err_code = 0;
    3144        1334 :     char       *condname = NULL;
    3145        1334 :     char       *err_message = NULL;
    3146        1334 :     char       *err_detail = NULL;
    3147        1334 :     char       *err_hint = NULL;
    3148        1334 :     char       *err_column = NULL;
    3149        1334 :     char       *err_constraint = NULL;
    3150        1334 :     char       *err_datatype = NULL;
    3151        1334 :     char       *err_table = NULL;
    3152        1334 :     char       *err_schema = NULL;
    3153             :     MemoryContext stmt_mcontext;
    3154             :     ListCell   *lc;
    3155             : 
    3156             :     /* RAISE with no parameters: re-throw current exception */
    3157        1343 :     if (stmt->condname == NULL && stmt->message == NULL &&
    3158           9 :         stmt->options == NIL)
    3159             :     {
    3160           6 :         if (estate->cur_error != NULL)
    3161           5 :             ReThrowError(estate->cur_error);
    3162             :         /* oops, we're not inside a handler */
    3163           1 :         ereport(ERROR,
    3164             :                 (errcode(ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER),
    3165             :                  errmsg("RAISE without parameters cannot be used outside an exception handler")));
    3166             :     }
    3167             : 
    3168             :     /* We'll need to accumulate the various strings in stmt_mcontext */
    3169        1328 :     stmt_mcontext = get_stmt_mcontext(estate);
    3170             : 
    3171        1328 :     if (stmt->condname)
    3172             :     {
    3173           9 :         err_code = plpgsql_recognize_err_condition(stmt->condname, true);
    3174           9 :         condname = MemoryContextStrdup(stmt_mcontext, stmt->condname);
    3175             :     }
    3176             : 
    3177        1328 :     if (stmt->message)
    3178             :     {
    3179             :         StringInfoData ds;
    3180             :         ListCell   *current_param;
    3181             :         char       *cp;
    3182             :         MemoryContext oldcontext;
    3183             : 
    3184             :         /* build string in stmt_mcontext */
    3185        1316 :         oldcontext = MemoryContextSwitchTo(stmt_mcontext);
    3186        1316 :         initStringInfo(&ds);
    3187        1316 :         MemoryContextSwitchTo(oldcontext);
    3188             : 
    3189        1316 :         current_param = list_head(stmt->params);
    3190             : 
    3191       23747 :         for (cp = stmt->message; *cp; cp++)
    3192             :         {
    3193             :             /*
    3194             :              * Occurrences of a single % are replaced by the next parameter's
    3195             :              * external representation. Double %'s are converted to one %.
    3196             :              */
    3197       22435 :             if (cp[0] == '%')
    3198             :             {
    3199             :                 Oid         paramtypeid;
    3200             :                 int32       paramtypmod;
    3201             :                 Datum       paramvalue;
    3202             :                 bool        paramisnull;
    3203             :                 char       *extval;
    3204             : 
    3205        2550 :                 if (cp[1] == '%')
    3206             :                 {
    3207           1 :                     appendStringInfoChar(&ds, '%');
    3208           1 :                     cp++;
    3209           1 :                     continue;
    3210             :                 }
    3211             : 
    3212             :                 /* should have been checked at compile time */
    3213        2549 :                 if (current_param == NULL)
    3214           0 :                     elog(ERROR, "unexpected RAISE parameter list length");
    3215             : 
    3216        2549 :                 paramvalue = exec_eval_expr(estate,
    3217        2549 :                                             (PLpgSQL_expr *) lfirst(current_param),
    3218             :                                             &paramisnull,
    3219             :                                             &paramtypeid,
    3220             :                                             &paramtypmod);
    3221             : 
    3222        2545 :                 if (paramisnull)
    3223           5 :                     extval = "<NULL>";
    3224             :                 else
    3225        2540 :                     extval = convert_value_to_string(estate,
    3226             :                                                      paramvalue,
    3227             :                                                      paramtypeid);
    3228        2545 :                 appendStringInfoString(&ds, extval);
    3229        2545 :                 current_param = lnext(current_param);
    3230        2545 :                 exec_eval_cleanup(estate);
    3231             :             }
    3232             :             else
    3233       19885 :                 appendStringInfoChar(&ds, cp[0]);
    3234             :         }
    3235             : 
    3236             :         /* should have been checked at compile time */
    3237        1312 :         if (current_param != NULL)
    3238           0 :             elog(ERROR, "unexpected RAISE parameter list length");
    3239             : 
    3240        1312 :         err_message = ds.data;
    3241             :     }
    3242             : 
    3243        1349 :     foreach(lc, stmt->options)
    3244             :     {
    3245          27 :         PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
    3246             :         Datum       optionvalue;
    3247             :         bool        optionisnull;
    3248             :         Oid         optiontypeid;
    3249             :         int32       optiontypmod;
    3250             :         char       *extval;
    3251             : 
    3252          27 :         optionvalue = exec_eval_expr(estate, opt->expr,
    3253             :                                      &optionisnull,
    3254             :                                      &optiontypeid,
    3255             :                                      &optiontypmod);
    3256          27 :         if (optionisnull)
    3257           0 :             ereport(ERROR,
    3258             :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    3259             :                      errmsg("RAISE statement option cannot be null")));
    3260             : 
    3261          27 :         extval = convert_value_to_string(estate, optionvalue, optiontypeid);
    3262             : 
    3263          27 :         switch (opt->opt_type)
    3264             :         {
    3265             :             case PLPGSQL_RAISEOPTION_ERRCODE:
    3266           7 :                 if (err_code)
    3267           1 :                     ereport(ERROR,
    3268             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3269             :                              errmsg("RAISE option already specified: %s",
    3270             :                                     "ERRCODE")));
    3271           6 :                 err_code = plpgsql_recognize_err_condition(extval, true);
    3272           6 :                 condname = MemoryContextStrdup(stmt_mcontext, extval);
    3273           6 :                 break;
    3274             :             case PLPGSQL_RAISEOPTION_MESSAGE:
    3275           6 :                 SET_RAISE_OPTION_TEXT(err_message, "MESSAGE");
    3276           5 :                 break;
    3277             :             case PLPGSQL_RAISEOPTION_DETAIL:
    3278           7 :                 SET_RAISE_OPTION_TEXT(err_detail, "DETAIL");
    3279           7 :                 break;
    3280             :             case PLPGSQL_RAISEOPTION_HINT:
    3281           2 :                 SET_RAISE_OPTION_TEXT(err_hint, "HINT");
    3282           2 :                 break;
    3283             :             case PLPGSQL_RAISEOPTION_COLUMN:
    3284           1 :                 SET_RAISE_OPTION_TEXT(err_column, "COLUMN");
    3285           1 :                 break;
    3286             :             case PLPGSQL_RAISEOPTION_CONSTRAINT:
    3287           1 :                 SET_RAISE_OPTION_TEXT(err_constraint, "CONSTRAINT");
    3288           1 :                 break;
    3289             :             case PLPGSQL_RAISEOPTION_DATATYPE:
    3290           1 :                 SET_RAISE_OPTION_TEXT(err_datatype, "DATATYPE");
    3291           1 :                 break;
    3292             :             case PLPGSQL_RAISEOPTION_TABLE:
    3293           1 :                 SET_RAISE_OPTION_TEXT(err_table, "TABLE");
    3294           1 :                 break;
    3295             :             case PLPGSQL_RAISEOPTION_SCHEMA:
    3296           1 :                 SET_RAISE_OPTION_TEXT(err_schema, "SCHEMA");
    3297           1 :                 break;
    3298             :             default:
    3299           0 :                 elog(ERROR, "unrecognized raise option: %d", opt->opt_type);
    3300             :         }
    3301             : 
    3302          25 :         exec_eval_cleanup(estate);
    3303             :     }
    3304             : 
    3305             :     /* Default code if nothing specified */
    3306        1322 :     if (err_code == 0 && stmt->elog_level >= ERROR)
    3307          28 :         err_code = ERRCODE_RAISE_EXCEPTION;
    3308             : 
    3309             :     /* Default error message if nothing specified */
    3310        1322 :     if (err_message == NULL)
    3311             :     {
    3312           7 :         if (condname)
    3313             :         {
    3314           6 :             err_message = condname;
    3315           6 :             condname = NULL;
    3316             :         }
    3317             :         else
    3318           1 :             err_message = MemoryContextStrdup(stmt_mcontext,
    3319           1 :                                               unpack_sql_state(err_code));
    3320             :     }
    3321             : 
    3322             :     /*
    3323             :      * Throw the error (may or may not come back)
    3324             :      */
    3325        1322 :     ereport(stmt->elog_level,
    3326             :             (err_code ? errcode(err_code) : 0,
    3327             :              errmsg_internal("%s", err_message),
    3328             :              (err_detail != NULL) ? errdetail_internal("%s", err_detail) : 0,
    3329             :              (err_hint != NULL) ? errhint("%s", err_hint) : 0,
    3330             :              (err_column != NULL) ?
    3331             :              err_generic_string(PG_DIAG_COLUMN_NAME, err_column) : 0,
    3332             :              (err_constraint != NULL) ?
    3333             :              err_generic_string(PG_DIAG_CONSTRAINT_NAME, err_constraint) : 0,
    3334             :              (err_datatype != NULL) ?
    3335             :              err_generic_string(PG_DIAG_DATATYPE_NAME, err_datatype) : 0,
    3336             :              (err_table != NULL) ?
    3337             :              err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
    3338             :              (err_schema != NULL) ?
    3339             :              err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0));
    3340             : 
    3341             :     /* Clean up transient strings */
    3342        1281 :     MemoryContextReset(stmt_mcontext);
    3343             : 
    3344        1281 :     return PLPGSQL_RC_OK;
    3345             : }
    3346             : 
    3347             : /* ----------
    3348             :  * exec_stmt_assert         Assert statement
    3349             :  * ----------
    3350             :  */
    3351             : static int
    3352           6 : exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
    3353             : {
    3354             :     bool        value;
    3355             :     bool        isnull;
    3356             : 
    3357             :     /* do nothing when asserts are not enabled */
    3358           6 :     if (!plpgsql_check_asserts)
    3359           1 :         return PLPGSQL_RC_OK;
    3360             : 
    3361           5 :     value = exec_eval_boolean(estate, stmt->cond, &isnull);
    3362           5 :     exec_eval_cleanup(estate);
    3363             : 
    3364           5 :     if (isnull || !value)
    3365             :     {
    3366           4 :         char       *message = NULL;
    3367             : 
    3368           4 :         if (stmt->message != NULL)
    3369             :         {
    3370             :             Datum       val;
    3371             :             Oid         typeid;
    3372             :             int32       typmod;
    3373             : 
    3374           2 :             val = exec_eval_expr(estate, stmt->message,
    3375             :                                  &isnull, &typeid, &typmod);
    3376           2 :             if (!isnull)
    3377           2 :                 message = convert_value_to_string(estate, val, typeid);
    3378             :             /* we mustn't do exec_eval_cleanup here */
    3379             :         }
    3380             : 
    3381           4 :         ereport(ERROR,
    3382             :                 (errcode(ERRCODE_ASSERT_FAILURE),
    3383             :                  message ? errmsg_internal("%s", message) :
    3384             :                  errmsg("assertion failed")));
    3385             :     }
    3386             : 
    3387           1 :     return PLPGSQL_RC_OK;
    3388             : }
    3389             : 
    3390             : /* ----------
    3391             :  * Initialize a mostly empty execution state
    3392             :  * ----------
    3393             :  */
    3394             : static void
    3395       12326 : plpgsql_estate_setup(PLpgSQL_execstate *estate,
    3396             :                      PLpgSQL_function *func,
    3397             :                      ReturnSetInfo *rsi,
    3398             :                      EState *simple_eval_estate)
    3399             : {
    3400             :     HASHCTL     ctl;
    3401             : 
    3402             :     /* this link will be restored at exit from plpgsql_call_handler */
    3403       12326 :     func->cur_estate = estate;
    3404             : 
    3405       12326 :     estate->func = func;
    3406             : 
    3407       12326 :     estate->retval = (Datum) 0;
    3408       12326 :     estate->retisnull = true;
    3409       12326 :     estate->rettype = InvalidOid;
    3410             : 
    3411       12326 :     estate->fn_rettype = func->fn_rettype;
    3412       12326 :     estate->retistuple = func->fn_retistuple;
    3413       12326 :     estate->retisset = func->fn_retset;
    3414             : 
    3415       12326 :     estate->readonly_func = func->fn_readonly;
    3416             : 
    3417       12326 :     estate->rettupdesc = NULL;
    3418       12326 :     estate->exitlabel = NULL;
    3419       12326 :     estate->cur_error = NULL;
    3420             : 
    3421       12326 :     estate->tuple_store = NULL;
    3422       12326 :     if (rsi)
    3423             :     {
    3424         105 :         estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
    3425         105 :         estate->tuple_store_owner = CurrentResourceOwner;
    3426             :     }
    3427             :     else
    3428             :     {
    3429       12221 :         estate->tuple_store_cxt = NULL;
    3430       12221 :         estate->tuple_store_owner = NULL;
    3431             :     }
    3432       12326 :     estate->rsi = rsi;
    3433             : 
    3434       12326 :     estate->found_varno = func->found_varno;
    3435       12326 :     estate->ndatums = func->ndatums;
    3436       12326 :     estate->datums = palloc(sizeof(PLpgSQL_datum *) * estate->ndatums);
    3437             :     /* caller is expected to fill the datums array */
    3438             : 
    3439             :     /* initialize ParamListInfo with one entry per datum, all invalid */
    3440       12326 :     estate->paramLI = (ParamListInfo)
    3441       12326 :         palloc0(offsetof(ParamListInfoData, params) +
    3442       12326 :                 estate->ndatums * sizeof(ParamExternData));
    3443       12326 :     estate->paramLI->paramFetch = plpgsql_param_fetch;
    3444       12326 :     estate->paramLI->paramFetchArg = (void *) estate;
    3445       12326 :     estate->paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
    3446       12326 :     estate->paramLI->parserSetupArg = NULL; /* filled during use */
    3447       12326 :     estate->paramLI->numParams = estate->ndatums;
    3448       12326 :     estate->paramLI->paramMask = NULL;
    3449       12326 :     estate->params_dirty = false;
    3450             : 
    3451             :     /* set up for use of appropriate simple-expression EState and cast hash */
    3452       12326 :     if (simple_eval_estate)
    3453             :     {
    3454          39 :         estate->simple_eval_estate = simple_eval_estate;
    3455             :         /* Private cast hash just lives in function's main context */
    3456          39 :         memset(&ctl, 0, sizeof(ctl));
    3457          39 :         ctl.keysize = sizeof(plpgsql_CastHashKey);
    3458          39 :         ctl.entrysize = sizeof(plpgsql_CastHashEntry);
    3459          39 :         ctl.hcxt = CurrentMemoryContext;
    3460          39 :         estate->cast_hash = hash_create("PLpgSQL private cast cache",
    3461             :                                         16, /* start small and extend */
    3462             :                                         &ctl,
    3463             :                                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
    3464          39 :         estate->cast_hash_context = CurrentMemoryContext;
    3465             :     }
    3466             :     else
    3467             :     {
    3468       12287 :         estate->simple_eval_estate = shared_simple_eval_estate;
    3469             :         /* Create the session-wide cast-info hash table if we didn't already */
    3470       12287 :         if (shared_cast_hash == NULL)
    3471             :         {
    3472          32 :             shared_cast_context = AllocSetContextCreate(TopMemoryContext,
    3473             :                                                         "PLpgSQL cast info",
    3474             :                                                         ALLOCSET_DEFAULT_SIZES);
    3475          32 :             memset(&ctl, 0, sizeof(ctl));
    3476          32 :             ctl.keysize = sizeof(plpgsql_CastHashKey);
    3477          32 :             ctl.entrysize = sizeof(plpgsql_CastHashEntry);
    3478          32 :             ctl.hcxt = shared_cast_context;
    3479          32 :             shared_cast_hash = hash_create("PLpgSQL cast cache",
    3480             :                                            16,  /* start small and extend */
    3481             :                                            &ctl,
    3482             :                                            HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
    3483             :         }
    3484       12287 :         estate->cast_hash = shared_cast_hash;
    3485       12287 :         estate->cast_hash_context = shared_cast_context;
    3486             :     }
    3487             : 
    3488             :     /*
    3489             :      * We start with no stmt_mcontext; one will be created only if needed.
    3490             :      * That context will be a direct child of the function's main execution
    3491             :      * context.  Additional stmt_mcontexts might be created as children of it.
    3492             :      */
    3493       12326 :     estate->stmt_mcontext = NULL;
    3494       12326 :     estate->stmt_mcontext_parent = CurrentMemoryContext;
    3495             : 
    3496       12326 :     estate->eval_tuptable = NULL;
    3497       12326 :     estate->eval_processed = 0;
    3498       12326 :     estate->eval_lastoid = InvalidOid;
    3499       12326 :     estate->eval_econtext = NULL;
    3500             : 
    3501       12326 :     estate->err_stmt = NULL;
    3502       12326 :     estate->err_text = NULL;
    3503             : 
    3504       12326 :     estate->plugin_info = NULL;
    3505             : 
    3506             :     /*
    3507             :      * Create an EState and ExprContext for evaluation of simple expressions.
    3508             :      */
    3509       12326 :     plpgsql_create_econtext(estate);
    3510             : 
    3511             :     /*
    3512             :      * Let the plugin see this function before we initialize any local
    3513             :      * PL/pgSQL variables - note that we also give the plugin a few function
    3514             :      * pointers so it can call back into PL/pgSQL for doing things like
    3515             :      * variable assignments and stack traces
    3516             :      */
    3517       12326 :     if (*plpgsql_plugin_ptr)
    3518             :     {
    3519           0 :         (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
    3520           0 :         (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
    3521             : 
    3522           0 :         if ((*plpgsql_plugin_ptr)->func_setup)
    3523           0 :             ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
    3524             :     }
    3525       12326 : }
    3526             : 
    3527             : /* ----------
    3528             :  * Release temporary memory used by expression/subselect evaluation
    3529             :  *
    3530             :  * NB: the result of the evaluation is no longer valid after this is done,
    3531             :  * unless it is a pass-by-value datatype.
    3532             :  *
    3533             :  * NB: if you change this code, see also the hacks in exec_assign_value's
    3534             :  * PLPGSQL_DTYPE_ARRAYELEM case for partial cleanup after subscript evals.
    3535             :  * ----------
    3536             :  */
    3537             : static void
    3538       38366 : exec_eval_cleanup(PLpgSQL_execstate *estate)
    3539             : {
    3540             :     /* Clear result of a full SPI_execute */
    3541       38366 :     if (estate->eval_tuptable != NULL)
    3542         726 :         SPI_freetuptable(estate->eval_tuptable);
    3543       38366 :     estate->eval_tuptable = NULL;
    3544             : 
    3545             :     /*
    3546             :      * Clear result of exec_eval_simple_expr (but keep the econtext).  This
    3547             :      * also clears any short-lived allocations done via get_eval_mcontext.
    3548             :      */
    3549       38366 :     if (estate->eval_econtext != NULL)
    3550       26158 :         ResetExprContext(estate->eval_econtext);
    3551       38366 : }
    3552             : 
    3553             : 
    3554             : /* ----------
    3555             :  * Generate a prepared plan
    3556             :  * ----------
    3557             :  */
    3558             : static void
    3559        1589 : exec_prepare_plan(PLpgSQL_execstate *estate,
    3560             :                   PLpgSQL_expr *expr, int cursorOptions)
    3561             : {
    3562             :     SPIPlanPtr  plan;
    3563             : 
    3564             :     /*
    3565             :      * The grammar can't conveniently set expr->func while building the parse
    3566             :      * tree, so make sure it's set before parser hooks need it.
    3567             :      */
    3568        1589 :     expr->func = estate->func;
    3569             : 
    3570             :     /*
    3571             :      * Generate and save the plan
    3572             :      */
    3573        1589 :     plan = SPI_prepare_params(expr->query,
    3574             :                               (ParserSetupHook) plpgsql_parser_setup,
    3575             :                               (void *) expr,
    3576             :                               cursorOptions);
    3577        1584 :     if (plan == NULL)
    3578             :     {
    3579             :         /* Some SPI errors deserve specific error messages */
    3580           0 :         switch (SPI_result)
    3581             :         {
    3582             :             case SPI_ERROR_COPY:
    3583           0 :                 ereport(ERROR,
    3584             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3585             :                          errmsg("cannot COPY to/from client in PL/pgSQL")));
    3586             :             case SPI_ERROR_TRANSACTION:
    3587           0 :                 ereport(ERROR,
    3588             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3589             :                          errmsg("cannot begin/end transactions in PL/pgSQL"),
    3590             :                          errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
    3591             :             default:
    3592           0 :                 elog(ERROR, "SPI_prepare_params failed for \"%s\": %s",
    3593             :                      expr->query, SPI_result_code_string(SPI_result));
    3594             :         }
    3595             :     }
    3596        1584 :     SPI_keepplan(plan);
    3597        1584 :     expr->plan = plan;
    3598             : 
    3599             :     /* Check to see if it's a simple expression */
    3600        1584 :     exec_simple_check_plan(estate, expr);
    3601             : 
    3602             :     /*
    3603             :      * Mark expression as not using a read-write param.  exec_assign_value has
    3604             :      * to take steps to override this if appropriate; that seems cleaner than
    3605             :      * adding parameters to all other callers.
    3606             :      */
    3607        1579 :     expr->rwparam = -1;
    3608        1579 : }
    3609             : 
    3610             : 
    3611             : /* ----------
    3612             :  * exec_stmt_execsql            Execute an SQL statement (possibly with INTO).
    3613             :  *
    3614             :  * Note: some callers rely on this not touching stmt_mcontext.  If it ever
    3615             :  * needs to use that, fix those callers to push/pop stmt_mcontext.
    3616             :  * ----------
    3617             :  */
    3618             : static int
    3619        1909 : exec_stmt_execsql(PLpgSQL_execstate *estate,
    3620             :                   PLpgSQL_stmt_execsql *stmt)
    3621             : {
    3622             :     ParamListInfo paramLI;
    3623             :     long        tcount;
    3624             :     int         rc;
    3625        1909 :     PLpgSQL_expr *expr = stmt->sqlstmt;
    3626             : 
    3627             :     /*
    3628             :      * On the first call for this statement generate the plan, and detect
    3629             :      * whether the statement is INSERT/UPDATE/DELETE
    3630             :      */
    3631        1909 :     if (expr->plan == NULL)
    3632             :     {
    3633             :         ListCell   *l;
    3634             : 
    3635         146 :         exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
    3636         145 :         stmt->mod_stmt = false;
    3637         290 :         foreach(l, SPI_plan_get_plan_sources(expr->plan))
    3638             :         {
    3639         145 :             CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l);
    3640             :             ListCell   *l2;
    3641             : 
    3642         290 :             foreach(l2, plansource->query_list)
    3643             :             {
    3644         145 :                 Query      *q = lfirst_node(Query, l2);
    3645             : 
    3646         145 :                 if (q->canSetTag)
    3647             :                 {
    3648         257 :                     if (q->commandType == CMD_INSERT ||
    3649         201 :                         q->commandType == CMD_UPDATE ||
    3650          89 :                         q->commandType == CMD_DELETE)
    3651          64 :                         stmt->mod_stmt = true;
    3652             :                 }
    3653             :             }
    3654             :         }
    3655             :     }
    3656             : 
    3657             :     /*
    3658             :      * Set up ParamListInfo to pass to executor
    3659             :      */
    3660        1908 :     paramLI = setup_param_list(estate, expr);
    3661             : 
    3662             :     /*
    3663             :      * If we have INTO, then we only need one row back ... but if we have INTO
    3664             :      * STRICT, ask for two rows, so that we can verify the statement returns
    3665             :      * only one.  INSERT/UPDATE/DELETE are always treated strictly. Without
    3666             :      * INTO, just run the statement to completion (tcount = 0).
    3667             :      *
    3668             :      * We could just ask for two rows always when using INTO, but there are
    3669             :      * some cases where demanding the extra row costs significant time, eg by
    3670             :      * forcing completion of a sequential scan.  So don't do it unless we need
    3671             :      * to enforce strictness.
    3672             :      */
    3673        1908 :     if (stmt->into)
    3674             :     {
    3675         583 :         if (stmt->strict || stmt->mod_stmt)
    3676          63 :             tcount = 2;
    3677             :         else
    3678         520 :             tcount = 1;
    3679             :     }
    3680             :     else
    3681        1325 :         tcount = 0;
    3682             : 
    3683             :     /*
    3684             :      * Execute the plan
    3685             :      */
    3686        1908 :     rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
    3687        1908 :                                          estate->readonly_func, tcount);
    3688             : 
    3689             :     /*
    3690             :      * Check for error, and set FOUND if appropriate (for historical reasons
    3691             :      * we set FOUND only for certain query types).  Also Assert that we
    3692             :      * identified the statement type the same as SPI did.
    3693             :      */
    3694        1899 :     switch (rc)
    3695             :     {
    3696             :         case SPI_OK_SELECT:
    3697         525 :             Assert(!stmt->mod_stmt);
    3698         525 :             exec_set_found(estate, (SPI_processed != 0));
    3699         525 :             break;
    3700             : 
    3701             :         case SPI_OK_INSERT:
    3702             :         case SPI_OK_UPDATE:
    3703             :         case SPI_OK_DELETE:
    3704             :         case SPI_OK_INSERT_RETURNING:
    3705             :         case SPI_OK_UPDATE_RETURNING:
    3706             :         case SPI_OK_DELETE_RETURNING:
    3707         359 :             Assert(stmt->mod_stmt);
    3708         359 :             exec_set_found(estate, (SPI_processed != 0));
    3709         359 :             break;
    3710             : 
    3711             :         case SPI_OK_SELINTO:
    3712             :         case SPI_OK_UTILITY:
    3713        1015 :             Assert(!stmt->mod_stmt);
    3714        1015 :             break;
    3715             : 
    3716             :         case SPI_OK_REWRITTEN:
    3717           0 :             Assert(!stmt->mod_stmt);
    3718             : 
    3719             :             /*
    3720             :              * The command was rewritten into another kind of command. It's
    3721             :              * not clear what FOUND would mean in that case (and SPI doesn't
    3722             :              * return the row count either), so just set it to false.
    3723             :              */
    3724           0 :             exec_set_found(estate, false);
    3725           0 :             break;
    3726             : 
    3727             :             /* Some SPI errors deserve specific error messages */
    3728             :         case SPI_ERROR_COPY:
    3729           0 :             ereport(ERROR,
    3730             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3731             :                      errmsg("cannot COPY to/from client in PL/pgSQL")));
    3732             :         case SPI_ERROR_TRANSACTION:
    3733           0 :             ereport(ERROR,
    3734             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3735             :                      errmsg("cannot begin/end transactions in PL/pgSQL"),
    3736             :                      errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
    3737             : 
    3738             :         default:
    3739           0 :             elog(ERROR, "SPI_execute_plan_with_paramlist failed executing query \"%s\": %s",
    3740             :                  expr->query, SPI_result_code_string(rc));
    3741             :     }
    3742             : 
    3743             :     /* All variants should save result info for GET DIAGNOSTICS */
    3744        1899 :     estate->eval_processed = SPI_processed;
    3745        1899 :     estate->eval_lastoid = SPI_lastoid;
    3746             : 
    3747             :     /* Process INTO if present */
    3748        1899 :     if (stmt->into)
    3749             :     {
    3750         580 :         SPITupleTable *tuptab = SPI_tuptable;
    3751         580 :         uint64      n = SPI_processed;
    3752         580 :         PLpgSQL_rec *rec = NULL;
    3753         580 :         PLpgSQL_row *row = NULL;
    3754             : 
    3755             :         /* If the statement did not return a tuple table, complain */
    3756         580 :         if (tuptab == NULL)
    3757           0 :             ereport(ERROR,
    3758             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    3759             :                      errmsg("INTO used with a command that cannot return data")));
    3760             : 
    3761             :         /* Determine if we assign to a record or a row */
    3762         580 :         if (stmt->rec != NULL)
    3763         458 :             rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
    3764         122 :         else if (stmt->row != NULL)
    3765         122 :             row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
    3766             :         else
    3767           0 :             elog(ERROR, "unsupported target");
    3768             : 
    3769             :         /*
    3770             :          * If SELECT ... INTO specified STRICT, and the query didn't find
    3771             :          * exactly one row, throw an error.  If STRICT was not specified, then
    3772             :          * allow the query to find any number of rows.
    3773             :          */
    3774         580 :         if (n == 0)
    3775             :         {
    3776          10 :             if (stmt->strict)
    3777             :             {
    3778             :                 char       *errdetail;
    3779             : 
    3780           2 :                 if (estate->func->print_strict_params)
    3781           1 :                     errdetail = format_expr_params(estate, expr);
    3782             :                 else
    3783           1 :                     errdetail = NULL;
    3784             : 
    3785           2 :                 ereport(ERROR,
    3786             :                         (errcode(ERRCODE_NO_DATA_FOUND),
    3787             :                          errmsg("query returned no rows"),
    3788             :                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
    3789             :             }
    3790             :             /* set the target to NULL(s) */
    3791           8 :             exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
    3792             :         }
    3793             :         else
    3794             :         {
    3795         570 :             if (n > 1 && (stmt->strict || stmt->mod_stmt))
    3796             :             {
    3797             :                 char       *errdetail;
    3798             : 
    3799           6 :                 if (estate->func->print_strict_params)
    3800           3 :                     errdetail = format_expr_params(estate, expr);
    3801             :                 else
    3802           3 :                     errdetail = NULL;
    3803             : 
    3804           6 :                 ereport(ERROR,
    3805             :                         (errcode(ERRCODE_TOO_MANY_ROWS),
    3806             :                          errmsg("query returned more than one row"),
    3807             :                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
    3808             :             }
    3809             :             /* Put the first result row into the target */
    3810         564 :             exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
    3811             :         }
    3812             : 
    3813             :         /* Clean up */
    3814         572 :         exec_eval_cleanup(estate);
    3815         572 :         SPI_freetuptable(SPI_tuptable);
    3816             :     }
    3817             :     else
    3818             :     {
    3819             :         /* If the statement returned a tuple table, complain */
    3820        1319 :         if (SPI_tuptable != NULL)
    3821           0 :             ereport(ERROR,
    3822             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    3823             :                      errmsg("query has no destination for result data"),
    3824             :                      (rc == SPI_OK_SELECT) ? errhint("If you want to discard the results of a SELECT, use PERFORM instead.") : 0));
    3825             :     }
    3826             : 
    3827        1891 :     return PLPGSQL_RC_OK;
    3828             : }
    3829             : 
    3830             : 
    3831             : /* ----------
    3832             :  * exec_stmt_dynexecute         Execute a dynamic SQL query
    3833             :  *                  (possibly with INTO).
    3834             :  * ----------
    3835             :  */
    3836             : static int
    3837         583 : exec_stmt_dynexecute(PLpgSQL_execstate *estate,
    3838             :                      PLpgSQL_stmt_dynexecute *stmt)
    3839             : {
    3840             :     Datum       query;
    3841             :     bool        isnull;
    3842             :     Oid         restype;
    3843             :     int32       restypmod;
    3844             :     char       *querystr;
    3845             :     int         exec_res;
    3846         583 :     PreparedParamsData *ppd = NULL;
    3847         583 :     MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
    3848             : 
    3849             :     /*
    3850             :      * First we evaluate the string expression after the EXECUTE keyword. Its
    3851             :      * result is the querystring we have to execute.
    3852             :      */
    3853         583 :     query = exec_eval_expr(estate, stmt->query, &isnull, &restype, &restypmod);
    3854         583 :     if (isnull)
    3855           0 :         ereport(ERROR,
    3856             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    3857             :                  errmsg("query string argument of EXECUTE is null")));
    3858             : 
    3859             :     /* Get the C-String representation */
    3860         583 :     querystr = convert_value_to_string(estate, query, restype);
    3861             : 
    3862             :     /* copy it into the stmt_mcontext before we clean up */
    3863         583 :     querystr = MemoryContextStrdup(stmt_mcontext, querystr);
    3864             : 
    3865         583 :     exec_eval_cleanup(estate);
    3866             : 
    3867             :     /*
    3868             :      * Execute the query without preparing a saved plan.
    3869             :      */
    3870         583 :     if (stmt->params)
    3871             :     {
    3872           3 :         ppd = exec_eval_using_params(estate, stmt->params);
    3873           6 :         exec_res = SPI_execute_with_args(querystr,
    3874             :                                          ppd->nargs, ppd->types,
    3875           3 :                                          ppd->values, ppd->nulls,
    3876           3 :                                          estate->readonly_func, 0);
    3877             :     }
    3878             :     else
    3879         580 :         exec_res = SPI_execute(querystr, estate->readonly_func, 0);
    3880             : 
    3881         569 :     switch (exec_res)
    3882             :     {
    3883             :         case SPI_OK_SELECT:
    3884             :         case SPI_OK_INSERT:
    3885             :         case SPI_OK_UPDATE:
    3886             :         case SPI_OK_DELETE:
    3887             :         case SPI_OK_INSERT_RETURNING:
    3888             :         case SPI_OK_UPDATE_RETURNING:
    3889             :         case SPI_OK_DELETE_RETURNING:
    3890             :         case SPI_OK_UTILITY:
    3891             :         case SPI_OK_REWRITTEN:
    3892         569 :             break;
    3893             : 
    3894             :         case 0:
    3895             : 
    3896             :             /*
    3897             :              * Also allow a zero return, which implies the querystring
    3898             :              * contained no commands.
    3899             :              */
    3900           0 :             break;
    3901             : 
    3902             :         case SPI_OK_SELINTO:
    3903             : 
    3904             :             /*
    3905             :              * We want to disallow SELECT INTO for now, because its behavior
    3906             :              * is not consistent with SELECT INTO in a normal plpgsql context.
    3907             :              * (We need to reimplement EXECUTE to parse the string as a
    3908             :              * plpgsql command, not just feed it to SPI_execute.)  This is not
    3909             :              * a functional limitation because CREATE TABLE AS is allowed.
    3910             :              */
    3911           0 :             ereport(ERROR,
    3912             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3913             :                      errmsg("EXECUTE of SELECT ... INTO is not implemented"),
    3914             :                      errhint("You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.")));
    3915             :             break;
    3916             : 
    3917             :             /* Some SPI errors deserve specific error messages */
    3918             :         case SPI_ERROR_COPY:
    3919           0 :             ereport(ERROR,
    3920             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3921             :                      errmsg("cannot COPY to/from client in PL/pgSQL")));
    3922             :         case SPI_ERROR_TRANSACTION:
    3923           0 :             ereport(ERROR,
    3924             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3925             :                      errmsg("cannot begin/end transactions in PL/pgSQL"),
    3926             :                      errhint("Use a BEGIN block with an EXCEPTION clause instead.")));
    3927             : 
    3928             :         default:
    3929           0 :             elog(ERROR, "SPI_execute failed executing query \"%s\": %s",
    3930             :                  querystr, SPI_result_code_string(exec_res));
    3931             :             break;
    3932             :     }
    3933             : 
    3934             :     /* Save result info for GET DIAGNOSTICS */
    3935         569 :     estate->eval_processed = SPI_processed;
    3936         569 :     estate->eval_lastoid = SPI_lastoid;
    3937             : 
    3938             :     /* Process INTO if present */
    3939         569 :     if (stmt->into)
    3940             :     {
    3941         550 :         SPITupleTable *tuptab = SPI_tuptable;
    3942         550 :         uint64      n = SPI_processed;
    3943         550 :         PLpgSQL_rec *rec = NULL;
    3944         550 :         PLpgSQL_row *row = NULL;
    3945             : 
    3946             :         /* If the statement did not return a tuple table, complain */
    3947         550 :         if (tuptab == NULL)
    3948           0 :             ereport(ERROR,
    3949             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    3950             :                      errmsg("INTO used with a command that cannot return data")));
    3951             : 
    3952             :         /* Determine if we assign to a record or a row */
    3953         550 :         if (stmt->rec != NULL)
    3954           9 :             rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
    3955         541 :         else if (stmt->row != NULL)
    3956         541 :             row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
    3957             :         else
    3958           0 :             elog(ERROR, "unsupported target");
    3959             : 
    3960             :         /*
    3961             :          * If SELECT ... INTO specified STRICT, and the query didn't find
    3962             :          * exactly one row, throw an error.  If STRICT was not specified, then
    3963             :          * allow the query to find any number of rows.
    3964             :          */
    3965         550 :         if (n == 0)
    3966             :         {
    3967           2 :             if (stmt->strict)
    3968             :             {
    3969             :                 char       *errdetail;
    3970             : 
    3971           2 :                 if (estate->func->print_strict_params)
    3972           1 :                     errdetail = format_preparedparamsdata(estate, ppd);
    3973             :                 else
    3974           1 :                     errdetail = NULL;
    3975             : 
    3976           2 :                 ereport(ERROR,
    3977             :                         (errcode(ERRCODE_NO_DATA_FOUND),
    3978             :                          errmsg("query returned no rows"),
    3979             :                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
    3980             :             }
    3981             :             /* set the target to NULL(s) */
    3982           0 :             exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
    3983             :         }
    3984             :         else
    3985             :         {
    3986         548 :             if (n > 1 && stmt->strict)
    3987             :             {
    3988             :                 char       *errdetail;
    3989             : 
    3990           3 :                 if (estate->func->print_strict_params)
    3991           2 :                     errdetail = format_preparedparamsdata(estate, ppd);
    3992             :                 else
    3993           1 :                     errdetail = NULL;
    3994             : 
    3995           3 :                 ereport(ERROR,
    3996             :                         (errcode(ERRCODE_TOO_MANY_ROWS),
    3997             :                          errmsg("query returned more than one row"),
    3998             :                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
    3999             :             }
    4000             : 
    4001             :             /* Put the first result row into the target */
    4002         545 :             exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
    4003             :         }
    4004             :         /* clean up after exec_move_row() */
    4005         545 :         exec_eval_cleanup(estate);
    4006             :     }
    4007             :     else
    4008             :     {
    4009             :         /*
    4010             :          * It might be a good idea to raise an error if the query returned
    4011             :          * tuples that are being ignored, but historically we have not done
    4012             :          * that.
    4013             :          */
    4014             :     }
    4015             : 
    4016             :     /* Release any result from SPI_execute, as well as transient data */
    4017         564 :     SPI_freetuptable(SPI_tuptable);
    4018         564 :     MemoryContextReset(stmt_mcontext);
    4019             : 
    4020         564 :     return PLPGSQL_RC_OK;
    4021             : }
    4022             : 
    4023             : 
    4024             : /* ----------
    4025             :  * exec_stmt_dynfors            Execute a dynamic query, assign each
    4026             :  *                  tuple to a record or row and
    4027             :  *                  execute a group of statements
    4028             :  *                  for it.
    4029             :  * ----------
    4030             :  */
    4031             : static int
    4032         503 : exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
    4033             : {
    4034             :     Portal      portal;
    4035             :     int         rc;
    4036             : 
    4037         503 :     portal = exec_dynquery_with_params(estate, stmt->query, stmt->params,
    4038             :                                        NULL, 0);
    4039             : 
    4040             :     /*
    4041             :      * Execute the loop
    4042             :      */
    4043         503 :     rc = exec_for_query(estate, (PLpgSQL_stmt_forq *) stmt, portal, true);
    4044             : 
    4045             :     /*
    4046             :      * Close the implicit cursor
    4047             :      */
    4048         503 :     SPI_cursor_close(portal);
    4049             : 
    4050         503 :     return rc;
    4051             : }
    4052             : 
    4053             : 
    4054             : /* ----------
    4055             :  * exec_stmt_open           Execute an OPEN cursor statement
    4056             :  * ----------
    4057             :  */
    4058             : static int
    4059          19 : exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
    4060             : {
    4061             :     PLpgSQL_var *curvar;
    4062          19 :     MemoryContext stmt_mcontext = NULL;
    4063          19 :     char       *curname = NULL;
    4064             :     PLpgSQL_expr *query;
    4065             :     Portal      portal;
    4066             :     ParamListInfo paramLI;
    4067             : 
    4068             :     /* ----------
    4069             :      * Get the cursor variable and if it has an assigned name, check
    4070             :      * that it's not in use currently.
    4071             :      * ----------
    4072             :      */
    4073          19 :     curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
    4074          19 :     if (!curvar->isnull)
    4075             :     {
    4076             :         MemoryContext oldcontext;
    4077             : 
    4078             :         /* We only need stmt_mcontext to hold the cursor name string */
    4079          15 :         stmt_mcontext = get_stmt_mcontext(estate);
    4080          15 :         oldcontext = MemoryContextSwitchTo(stmt_mcontext);
    4081          15 :         curname = TextDatumGetCString(curvar->value);
    4082          15 :         MemoryContextSwitchTo(oldcontext);
    4083             : 
    4084          15 :         if (SPI_cursor_find(curname) != NULL)
    4085           0 :             ereport(ERROR,
    4086             :                     (errcode(ERRCODE_DUPLICATE_CURSOR),
    4087             :                      errmsg("cursor \"%s\" already in use", curname)));
    4088             :     }
    4089             : 
    4090             :     /* ----------
    4091             :      * Process the OPEN according to it's type.
    4092             :      * ----------
    4093             :      */
    4094          19 :     if (stmt->query != NULL)
    4095             :     {
    4096             :         /* ----------
    4097             :          * This is an OPEN refcursor FOR SELECT ...
    4098             :          *
    4099             :          * We just make sure the query is planned. The real work is
    4100             :          * done downstairs.
    4101             :          * ----------
    4102             :          */
    4103           4 :         query = stmt->query;
    4104           4 :         if (query->plan == NULL)
    4105           3 :             exec_prepare_plan(estate, query, stmt->cursor_options);
    4106             :     }
    4107          15 :     else if (stmt->dynquery != NULL)
    4108             :     {
    4109             :         /* ----------
    4110             :          * This is an OPEN refcursor FOR EXECUTE ...
    4111             :          * ----------
    4112             :          */
    4113           3 :         portal = exec_dynquery_with_params(estate,
    4114             :                                            stmt->dynquery,
    4115             :                                            stmt->params,
    4116             :                                            curname,
    4117             :                                            stmt->cursor_options);
    4118             : 
    4119             :         /*
    4120             :          * If cursor variable was NULL, store the generated portal name in it.
    4121             :          * Note: exec_dynquery_with_params already reset the stmt_mcontext, so
    4122             :          * curname is a dangling pointer here; but testing it for nullness is
    4123             :          * OK.
    4124             :          */
    4125           3 :         if (curname == NULL)
    4126           3 :             assign_text_var(estate, curvar, portal->name);
    4127             : 
    4128           3 :         return PLPGSQL_RC_OK;
    4129             :     }
    4130             :     else
    4131             :     {
    4132             :         /* ----------
    4133             :          * This is an OPEN cursor
    4134             :          *
    4135             :          * Note: parser should already have checked that statement supplies
    4136             :          * args iff cursor needs them, but we check again to be safe.
    4137             :          * ----------
    4138             :          */
    4139          12 :         if (stmt->argquery != NULL)
    4140             :         {
    4141             :             /* ----------
    4142             :              * OPEN CURSOR with args.  We fake a SELECT ... INTO ...
    4143             :              * statement to evaluate the args and put 'em into the
    4144             :              * internal row.
    4145             :              * ----------
    4146             :              */
    4147             :             PLpgSQL_stmt_execsql set_args;
    4148             : 
    4149           8 :             if (curvar->cursor_explicit_argrow < 0)
    4150           0 :                 ereport(ERROR,
    4151             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    4152             :                          errmsg("arguments given for cursor without arguments")));
    4153             : 
    4154           8 :             memset(&set_args, 0, sizeof(set_args));
    4155           8 :             set_args.cmd_type = PLPGSQL_STMT_EXECSQL;
    4156           8 :             set_args.lineno = stmt->lineno;
    4157           8 :             set_args.sqlstmt = stmt->argquery;
    4158           8 :             set_args.into = true;
    4159             :             /* XXX historically this has not been STRICT */
    4160           8 :             set_args.row = (PLpgSQL_row *)
    4161           8 :                 (estate->datums[curvar->cursor_explicit_argrow]);
    4162             : 
    4163           8 :             if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
    4164           0 :                 elog(ERROR, "open cursor failed during argument processing");
    4165             :         }
    4166             :         else
    4167             :         {
    4168           4 :             if (curvar->cursor_explicit_argrow >= 0)
    4169           0 :                 ereport(ERROR,
    4170             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    4171             :                          errmsg("arguments required for cursor")));
    4172             :         }
    4173             : 
    4174          11 :         query = curvar->cursor_explicit_expr;
    4175          11 :         if (query->plan == NULL)
    4176           9 :             exec_prepare_plan(estate, query, curvar->cursor_options);
    4177             :     }
    4178             : 
    4179             :     /*
    4180             :      * Set up short-lived ParamListInfo
    4181             :      */
    4182          15 :     paramLI = setup_unshared_param_list(estate, query);
    4183             : 
    4184             :     /*
    4185             :      * Open the cursor
    4186             :      */
    4187          15 :     portal = SPI_cursor_open_with_paramlist(curname, query->plan,
    4188             :                                             paramLI,
    4189          15 :                                             estate->readonly_func);
    4190          15 :     if (portal == NULL)
    4191           0 :         elog(ERROR, "could not open cursor: %s",
    4192             :              SPI_result_code_string(SPI_result));
    4193             : 
    4194             :     /*
    4195             :      * If cursor variable was NULL, store the generated portal name in it
    4196             :      */
    4197          15 :     if (curname == NULL)
    4198           1 :         assign_text_var(estate, curvar, portal->name);
    4199             : 
    4200             :     /* If we had any transient data, clean it up */
    4201          15 :     exec_eval_cleanup(estate);
    4202          15 :     if (stmt_mcontext)
    4203          14 :         MemoryContextReset(stmt_mcontext);
    4204             : 
    4205          15 :     return PLPGSQL_RC_OK;
    4206             : }
    4207             : 
    4208             : 
    4209             : /* ----------
    4210             :  * exec_stmt_fetch          Fetch from a cursor into a target, or just
    4211             :  *                          move the current position of the cursor
    4212             :  * ----------
    4213             :  */
    4214             : static int
    4215          56 : exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
    4216             : {
    4217             :     PLpgSQL_var *curvar;
    4218          56 :     PLpgSQL_rec *rec = NULL;
    4219          56 :     PLpgSQL_row *row = NULL;
    4220          56 :     long        how_many = stmt->how_many;
    4221             :     SPITupleTable *tuptab;
    4222             :     Portal      portal;
    4223             :     char       *curname;
    4224             :     uint64      n;
    4225             :     MemoryContext oldcontext;
    4226             : 
    4227             :     /* ----------
    4228             :      * Get the portal of the cursor by name
    4229             :      * ----------
    4230             :      */
    4231          56 :     curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
    4232          56 :     if (curvar->isnull)
    4233           0 :         ereport(ERROR,
    4234             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4235             :                  errmsg("cursor variable \"%s\" is null", curvar->refname)));
    4236             : 
    4237             :     /* Use eval_mcontext for short-lived string */
    4238          56 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4239          56 :     curname = TextDatumGetCString(curvar->value);
    4240          56 :     MemoryContextSwitchTo(oldcontext);
    4241             : 
    4242          56 :     portal = SPI_cursor_find(curname);
    4243          56 :     if (portal == NULL)
    4244           0 :         ereport(ERROR,
    4245             :                 (errcode(ERRCODE_UNDEFINED_CURSOR),
    4246             :                  errmsg("cursor \"%s\" does not exist", curname)));
    4247             : 
    4248             :     /* Calculate position for FETCH_RELATIVE or FETCH_ABSOLUTE */
    4249          56 :     if (stmt->expr)
    4250             :     {
    4251             :         bool        isnull;
    4252             : 
    4253             :         /* XXX should be doing this in LONG not INT width */
    4254          11 :         how_many = exec_eval_integer(estate, stmt->expr, &isnull);
    4255             : 
    4256          11 :         if (isnull)
    4257           0 :             ereport(ERROR,
    4258             :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4259             :                      errmsg("relative or absolute cursor position is null")));
    4260             : 
    4261          11 :         exec_eval_cleanup(estate);
    4262             :     }
    4263             : 
    4264          56 :     if (!stmt->is_move)
    4265             :     {
    4266             :         /* ----------
    4267             :          * Determine if we fetch into a record or a row
    4268             :          * ----------
    4269             :          */
    4270          49 :         if (stmt->rec != NULL)
    4271          16 :             rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
    4272          33 :         else if (stmt->row != NULL)
    4273          33 :             row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
    4274             :         else
    4275           0 :             elog(ERROR, "unsupported target");
    4276             : 
    4277             :         /* ----------
    4278             :          * Fetch 1 tuple from the cursor
    4279             :          * ----------
    4280             :          */
    4281          49 :         SPI_scroll_cursor_fetch(portal, stmt->direction, how_many);
    4282          48 :         tuptab = SPI_tuptable;
    4283          48 :         n = SPI_processed;
    4284             : 
    4285             :         /* ----------
    4286             :          * Set the target appropriately.
    4287             :          * ----------
    4288             :          */
    4289          48 :         if (n == 0)
    4290           8 :             exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
    4291             :         else
    4292          40 :             exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
    4293             : 
    4294          48 :         exec_eval_cleanup(estate);
    4295          48 :         SPI_freetuptable(tuptab);
    4296             :     }
    4297             :     else
    4298             :     {
    4299             :         /* Move the cursor */
    4300           7 :         SPI_scroll_cursor_move(portal, stmt->direction, how_many);
    4301           7 :         n = SPI_processed;
    4302             :     }
    4303             : 
    4304             :     /* Set the ROW_COUNT and the global FOUND variable appropriately. */
    4305          55 :     estate->eval_processed = n;
    4306          55 :     exec_set_found(estate, n != 0);
    4307             : 
    4308          55 :     return PLPGSQL_RC_OK;
    4309             : }
    4310             : 
    4311             : /* ----------
    4312             :  * exec_stmt_close          Close a cursor
    4313             :  * ----------
    4314             :  */
    4315             : static int
    4316          12 : exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt)
    4317             : {
    4318             :     PLpgSQL_var *curvar;
    4319             :     Portal      portal;
    4320             :     char       *curname;
    4321             :     MemoryContext oldcontext;
    4322             : 
    4323             :     /* ----------
    4324             :      * Get the portal of the cursor by name
    4325             :      * ----------
    4326             :      */
    4327          12 :     curvar = (PLpgSQL_var *) (estate->datums[stmt->curvar]);
    4328          12 :     if (curvar->isnull)
    4329           0 :         ereport(ERROR,
    4330             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4331             :                  errmsg("cursor variable \"%s\" is null", curvar->refname)));
    4332             : 
    4333             :     /* Use eval_mcontext for short-lived string */
    4334          12 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4335          12 :     curname = TextDatumGetCString(curvar->value);
    4336          12 :     MemoryContextSwitchTo(oldcontext);
    4337             : 
    4338          12 :     portal = SPI_cursor_find(curname);
    4339          12 :     if (portal == NULL)
    4340           0 :         ereport(ERROR,
    4341             :                 (errcode(ERRCODE_UNDEFINED_CURSOR),
    4342             :                  errmsg("cursor \"%s\" does not exist", curname)));
    4343             : 
    4344             :     /* ----------
    4345             :      * And close it.
    4346             :      * ----------
    4347             :      */
    4348          12 :     SPI_cursor_close(portal);
    4349             : 
    4350          12 :     return PLPGSQL_RC_OK;
    4351             : }
    4352             : 
    4353             : 
    4354             : /* ----------
    4355             :  * exec_assign_expr         Put an expression's result into a variable.
    4356             :  * ----------
    4357             :  */
    4358             : static void
    4359        2779 : exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
    4360             :                  PLpgSQL_expr *expr)
    4361             : {
    4362             :     Datum       value;
    4363             :     bool        isnull;
    4364             :     Oid         valtype;
    4365             :     int32       valtypmod;
    4366             : 
    4367             :     /*
    4368             :      * If first time through, create a plan for this expression, and then see
    4369             :      * if we can pass the target variable as a read-write parameter to the
    4370             :      * expression.  (This is a bit messy, but it seems cleaner than modifying
    4371             :      * the API of exec_eval_expr for the purpose.)
    4372             :      */
    4373        2779 :     if (expr->plan == NULL)
    4374             :     {
    4375         273 :         exec_prepare_plan(estate, expr, 0);
    4376         273 :         if (target->dtype == PLPGSQL_DTYPE_VAR)
    4377         246 :             exec_check_rw_parameter(expr, target->dno);
    4378             :     }
    4379             : 
    4380        2779 :     value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod);
    4381        2762 :     exec_assign_value(estate, target, value, isnull, valtype, valtypmod);
    4382        2748 :     exec_eval_cleanup(estate);
    4383        2748 : }
    4384             : 
    4385             : 
    4386             : /* ----------
    4387             :  * exec_assign_c_string     Put a C string into a text variable.
    4388             :  *
    4389             :  * We take a NULL pointer as signifying empty string, not SQL null.
    4390             :  *
    4391             :  * As with the underlying exec_assign_value, caller is expected to do
    4392             :  * exec_eval_cleanup later.
    4393             :  * ----------
    4394             :  */
    4395             : static void
    4396          19 : exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
    4397             :                      const char *str)
    4398             : {
    4399             :     text       *value;
    4400             :     MemoryContext oldcontext;
    4401             : 
    4402             :     /* Use eval_mcontext for short-lived text value */
    4403          19 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4404          19 :     if (str != NULL)
    4405          19 :         value = cstring_to_text(str);
    4406             :     else
    4407           0 :         value = cstring_to_text("");
    4408          19 :     MemoryContextSwitchTo(oldcontext);
    4409             : 
    4410          19 :     exec_assign_value(estate, target, PointerGetDatum(value), false,
    4411             :                       TEXTOID, -1);
    4412          19 : }
    4413             : 
    4414             : 
    4415             : /* ----------
    4416             :  * exec_assign_value            Put a value into a target datum
    4417             :  *
    4418             :  * Note: in some code paths, this will leak memory in the eval_mcontext;
    4419             :  * we assume that will be cleaned up later by exec_eval_cleanup.  We cannot
    4420             :  * call exec_eval_cleanup here for fear of destroying the input Datum value.
    4421             :  * ----------
    4422             :  */
    4423             : static void
    4424        6186 : exec_assign_value(PLpgSQL_execstate *estate,
    4425             :                   PLpgSQL_datum *target,
    4426             :                   Datum value, bool isNull,
    4427             :                   Oid valtype, int32 valtypmod)
    4428             : {
    4429        6186 :     switch (target->dtype)
    4430             :     {
    4431             :         case PLPGSQL_DTYPE_VAR:
    4432             :             {
    4433             :                 /*
    4434             :                  * Target is a variable
    4435             :                  */
    4436        6047 :                 PLpgSQL_var *var = (PLpgSQL_var *) target;
    4437             :                 Datum       newvalue;
    4438             : 
    4439       12094 :                 newvalue = exec_cast_value(estate,
    4440             :                                            value,
    4441             :                                            &isNull,
    4442             :                                            valtype,
    4443             :                                            valtypmod,
    4444        6047 :                                            var->datatype->typoid,
    4445        6047 :                                            var->datatype->atttypmod);
    4446             : 
    4447        6036 :                 if (isNull && var->notnull)
    4448           1 :                     ereport(ERROR,
    4449             :                             (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4450             :                              errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL",
    4451             :                                     var->refname)));
    4452             : 
    4453             :                 /*
    4454             :                  * If type is by-reference, copy the new value (which is
    4455             :                  * probably in the eval_mcontext) into the procedure's main
    4456             :                  * memory context.  But if it's a read/write reference to an
    4457             :                  * expanded object, no physical copy needs to happen; at most
    4458             :                  * we need to reparent the object's memory context.
    4459             :                  *
    4460             :                  * If it's an array, we force the value to be stored in R/W
    4461             :                  * expanded form.  This wins if the function later does, say,
    4462             :                  * a lot of array subscripting operations on the variable, and
    4463             :                  * otherwise might lose.  We might need to use a different
    4464             :                  * heuristic, but it's too soon to tell.  Also, are there
    4465             :                  * cases where it'd be useful to force non-array values into
    4466             :                  * expanded form?
    4467             :                  */
    4468        6035 :                 if (!var->datatype->typbyval && !isNull)
    4469             :                 {
    4470        4924 :                     if (var->datatype->typisarray &&
    4471         830 :                         !VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(newvalue)))
    4472             :                     {
    4473             :                         /* array and not already R/W, so apply expand_array */
    4474         818 :                         newvalue = expand_array(newvalue,
    4475             :                                                 CurrentMemoryContext,
    4476             :                                                 NULL);
    4477             :                     }
    4478             :                     else
    4479             :                     {
    4480             :                         /* else transfer value if R/W, else just datumCopy */
    4481        3282 :                         newvalue = datumTransfer(newvalue,
    4482             :                                                  false,
    4483        3282 :                                                  var->datatype->typlen);
    4484             :                     }
    4485             :                 }
    4486             : 
    4487             :                 /*
    4488             :                  * Now free the old value, if any, and assign the new one. But
    4489             :                  * skip the assignment if old and new values are the same.
    4490             :                  * Note that for expanded objects, this test is necessary and
    4491             :                  * cannot reliably be made any earlier; we have to be looking
    4492             :                  * at the object's standard R/W pointer to be sure pointer
    4493             :                  * equality is meaningful.
    4494             :                  */
    4495        6035 :                 if (var->value != newvalue || var->isnull || isNull)
    4496        5860 :                     assign_simple_var(estate, var, newvalue, isNull,
    4497        5860 :                                       (!var->datatype->typbyval && !isNull));
    4498        6035 :                 break;
    4499             :             }
    4500             : 
    4501             :         case PLPGSQL_DTYPE_ROW:
    4502             :             {
    4503             :                 /*
    4504             :                  * Target is a row variable
    4505             :                  */
    4506           9 :                 PLpgSQL_row *row = (PLpgSQL_row *) target;
    4507             : 
    4508           9 :                 if (isNull)
    4509             :                 {
    4510             :                     /* If source is null, just assign nulls to the row */
    4511           0 :                     exec_move_row(estate, NULL, row, NULL, NULL);
    4512             :                 }
    4513             :                 else
    4514             :                 {
    4515             :                     /* Source must be of RECORD or composite type */
    4516           9 :                     if (!type_is_rowtype(valtype))
    4517           0 :                         ereport(ERROR,
    4518             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    4519             :                                  errmsg("cannot assign non-composite value to a row variable")));
    4520           9 :                     exec_move_row_from_datum(estate, NULL, row, value);
    4521             :                 }
    4522           9 :                 break;
    4523             :             }
    4524             : 
    4525             :         case PLPGSQL_DTYPE_REC:
    4526             :             {
    4527             :                 /*
    4528             :                  * Target is a record variable
    4529             :                  */
    4530          28 :                 PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
    4531             : 
    4532          28 :                 if (isNull)
    4533             :                 {
    4534             :                     /* If source is null, just assign nulls to the record */
    4535           0 :                     exec_move_row(estate, rec, NULL, NULL, NULL);
    4536             :                 }
    4537             :                 else
    4538             :                 {
    4539             :                     /* Source must be of RECORD or composite type */
    4540          28 :                     if (!type_is_rowtype(valtype))
    4541           0 :                         ereport(ERROR,
    4542             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    4543             :                                  errmsg("cannot assign non-composite value to a record variable")));
    4544          28 :                     exec_move_row_from_datum(estate, rec, NULL, value);
    4545             :                 }
    4546          28 :                 break;
    4547             :             }
    4548             : 
    4549             :         case PLPGSQL_DTYPE_RECFIELD:
    4550             :             {
    4551             :                 /*
    4552             :                  * Target is a field of a record
    4553             :                  */
    4554          86 :                 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target;
    4555             :                 PLpgSQL_rec *rec;
    4556             :                 int         fno;
    4557             :                 HeapTuple   newtup;
    4558             :                 int         colnums[1];
    4559             :                 Datum       values[1];
    4560             :                 bool        nulls[1];
    4561             :                 Oid         atttype;
    4562             :                 int32       atttypmod;
    4563             : 
    4564          86 :                 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
    4565             : 
    4566             :                 /*
    4567             :                  * Check that there is already a tuple in the record. We need
    4568             :                  * that because records don't have any predefined field
    4569             :                  * structure.
    4570             :                  */
    4571          86 :                 if (!HeapTupleIsValid(rec->tup))
    4572           0 :                     ereport(ERROR,
    4573             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    4574             :                              errmsg("record \"%s\" is not assigned yet",
    4575             :                                     rec->refname),
    4576             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    4577             : 
    4578             :                 /*
    4579             :                  * Get the number of the record field to change.  Disallow
    4580             :                  * system columns because the code below won't cope.
    4581             :                  */
    4582          86 :                 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
    4583          86 :                 if (fno <= 0)
    4584           0 :                     ereport(ERROR,
    4585             :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
    4586             :                              errmsg("record \"%s\" has no field \"%s\"",
    4587             :                                     rec->refname, recfield->fieldname)));
    4588          86 :                 colnums[0] = fno;
    4589             : 
    4590             :                 /*
    4591             :                  * Now insert the new value, being careful to cast it to the
    4592             :                  * right type.
    4593             :                  */
    4594          86 :                 atttype = TupleDescAttr(rec->tupdesc, fno - 1)->atttypid;
    4595          86 :                 atttypmod = TupleDescAttr(rec->tupdesc, fno - 1)->atttypmod;
    4596          86 :                 values[0] = exec_cast_value(estate,
    4597             :                                             value,
    4598             :                                             &isNull,
    4599             :                                             valtype,
    4600             :                                             valtypmod,
    4601             :                                             atttype,
    4602             :                                             atttypmod);
    4603          86 :                 nulls[0] = isNull;
    4604             : 
    4605          86 :                 newtup = heap_modify_tuple_by_cols(rec->tup, rec->tupdesc,
    4606             :                                                    1, colnums, values, nulls);
    4607             : 
    4608          86 :                 if (rec->freetup)
    4609          10 :                     heap_freetuple(rec->tup);
    4610             : 
    4611          86 :                 rec->tup = newtup;
    4612          86 :                 rec->freetup = true;
    4613             : 
    4614          86 :                 break;
    4615             :             }
    4616             : 
    4617             :         case PLPGSQL_DTYPE_ARRAYELEM:
    4618             :             {
    4619             :                 /*
    4620             :                  * Target is an element of an array
    4621             :                  */
    4622             :                 PLpgSQL_arrayelem *arrayelem;
    4623             :                 int         nsubscripts;
    4624             :                 int         i;
    4625             :                 PLpgSQL_expr *subscripts[MAXDIM];
    4626             :                 int         subscriptvals[MAXDIM];
    4627             :                 Datum       oldarraydatum,
    4628             :                             newarraydatum,
    4629             :                             coerced_value;
    4630             :                 bool        oldarrayisnull;
    4631             :                 Oid         parenttypoid;
    4632             :                 int32       parenttypmod;
    4633             :                 SPITupleTable *save_eval_tuptable;
    4634             :                 MemoryContext oldcontext;
    4635             : 
    4636             :                 /*
    4637             :                  * We need to do subscript evaluation, which might require
    4638             :                  * evaluating general expressions; and the caller might have
    4639             :                  * done that too in order to prepare the input Datum.  We have
    4640             :                  * to save and restore the caller's SPI_execute result, if
    4641             :                  * any.
    4642             :                  */
    4643          16 :                 save_eval_tuptable = estate->eval_tuptable;
    4644          16 :                 estate->eval_tuptable = NULL;
    4645             : 
    4646             :                 /*
    4647             :                  * To handle constructs like x[1][2] := something, we have to
    4648             :                  * be prepared to deal with a chain of arrayelem datums. Chase
    4649             :                  * back to find the base array datum, and save the subscript
    4650             :                  * expressions as we go.  (We are scanning right to left here,
    4651             :                  * but want to evaluate the subscripts left-to-right to
    4652             :                  * minimize surprises.)  Note that arrayelem is left pointing
    4653             :                  * to the leftmost arrayelem datum, where we will cache the
    4654             :                  * array element type data.
    4655             :                  */
    4656          16 :                 nsubscripts = 0;
    4657             :                 do
    4658             :                 {
    4659          17 :                     arrayelem = (PLpgSQL_arrayelem *) target;
    4660          17 :                     if (nsubscripts >= MAXDIM)
    4661           0 :                         ereport(ERROR,
    4662             :                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    4663             :                                  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
    4664             :                                         nsubscripts + 1, MAXDIM)));
    4665          17 :                     subscripts[nsubscripts++] = arrayelem->subscript;
    4666          17 :                     target = estate->datums[arrayelem->arrayparentno];
    4667          17 :                 } while (target->dtype == PLPGSQL_DTYPE_ARRAYELEM);
    4668             : 
    4669             :                 /* Fetch current value of array datum */
    4670          16 :                 exec_eval_datum(estate, target,
    4671             :                                 &parenttypoid, &parenttypmod,
    4672             :                                 &oldarraydatum, &oldarrayisnull);
    4673             : 
    4674             :                 /* Update cached type data if necessary */
    4675          23 :                 if (arrayelem->parenttypoid != parenttypoid ||
    4676           7 :                     arrayelem->parenttypmod != parenttypmod)
    4677             :                 {
    4678             :                     Oid         arraytypoid;
    4679           9 :                     int32       arraytypmod = parenttypmod;
    4680             :                     int16       arraytyplen;
    4681             :                     Oid         elemtypoid;
    4682             :                     int16       elemtyplen;
    4683             :                     bool        elemtypbyval;
    4684             :                     char        elemtypalign;
    4685             : 
    4686             :                     /* If target is domain over array, reduce to base type */
    4687           9 :                     arraytypoid = getBaseTypeAndTypmod(parenttypoid,
    4688             :                                                        &arraytypmod);
    4689             : 
    4690             :                     /* ... and identify the element type */
    4691           9 :                     elemtypoid = get_element_type(arraytypoid);
    4692           9 :                     if (!OidIsValid(elemtypoid))
    4693           0 :                         ereport(ERROR,
    4694             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    4695             :                                  errmsg("subscripted object is not an array")));
    4696             : 
    4697             :                     /* Collect needed data about the types */
    4698           9 :                     arraytyplen = get_typlen(arraytypoid);
    4699             : 
    4700           9 :                     get_typlenbyvalalign(elemtypoid,
    4701             :                                          &elemtyplen,
    4702             :                                          &elemtypbyval,
    4703             :                                          &elemtypalign);
    4704             : 
    4705             :                     /* Now safe to update the cached data */
    4706           9 :                     arrayelem->parenttypoid = parenttypoid;
    4707           9 :                     arrayelem->parenttypmod = parenttypmod;
    4708           9 :                     arrayelem->arraytypoid = arraytypoid;
    4709           9 :                     arrayelem->arraytypmod = arraytypmod;
    4710           9 :                     arrayelem->arraytyplen = arraytyplen;
    4711           9 :                     arrayelem->elemtypoid = elemtypoid;
    4712           9 :                     arrayelem->elemtyplen = elemtyplen;
    4713           9 :                     arrayelem->elemtypbyval = elemtypbyval;
    4714           9 :                     arrayelem->elemtypalign = elemtypalign;
    4715             :                 }
    4716             : 
    4717             :                 /*
    4718             :                  * Evaluate the subscripts, switch into left-to-right order.
    4719             :                  * Like the expression built by ExecInitArrayRef(), complain
    4720             :                  * if any subscript is null.
    4721             :                  */
    4722          33 :                 for (i = 0; i < nsubscripts; i++)
    4723             :                 {
    4724             :                     bool        subisnull;
    4725             : 
    4726          17 :                     subscriptvals[i] =
    4727          17 :                         exec_eval_integer(estate,
    4728          17 :                                           subscripts[nsubscripts - 1 - i],
    4729             :                                           &subisnull);
    4730          17 :                     if (subisnull)
    4731           0 :                         ereport(ERROR,
    4732             :                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4733             :                                  errmsg("array subscript in assignment must not be null")));
    4734             : 
    4735             :                     /*
    4736             :                      * Clean up in case the subscript expression wasn't
    4737             :                      * simple. We can't do exec_eval_cleanup, but we can do
    4738             :                      * this much (which is safe because the integer subscript
    4739             :                      * value is surely pass-by-value), and we must do it in
    4740             :                      * case the next subscript expression isn't simple either.
    4741             :                      */
    4742          17 :                     if (estate->eval_tuptable != NULL)
    4743           2 :                         SPI_freetuptable(estate->eval_tuptable);
    4744          17 :                     estate->eval_tuptable = NULL;
    4745             :                 }
    4746             : 
    4747             :                 /* Now we can restore caller's SPI_execute result if any. */
    4748          16 :                 Assert(estate->eval_tuptable == NULL);
    4749          16 :                 estate->eval_tuptable = save_eval_tuptable;
    4750             : 
    4751             :                 /* Coerce source value to match array element type. */
    4752          16 :                 coerced_value = exec_cast_value(estate,
    4753             :                                                 value,
    4754             :                                                 &isNull,
    4755             :                                                 valtype,
    4756             :                                                 valtypmod,
    4757             :                                                 arrayelem->elemtypoid,
    4758             :                                                 arrayelem->arraytypmod);
    4759             : 
    4760             :                 /*
    4761             :                  * If the original array is null, cons up an empty array so
    4762             :                  * that the assignment can proceed; we'll end with a
    4763             :                  * one-element array containing just the assigned-to
    4764             :                  * subscript.  This only works for varlena arrays, though; for
    4765             :                  * fixed-length array types we skip the assignment.  We can't
    4766             :                  * support assignment of a null entry into a fixed-length
    4767             :                  * array, either, so that's a no-op too.  This is all ugly but
    4768             :                  * corresponds to the current behavior of execExpr*.c.
    4769             :                  */
    4770          13 :                 if (arrayelem->arraytyplen > 0 && /* fixed-length array? */
    4771           0 :                     (oldarrayisnull || isNull))
    4772        6169 :                     return;
    4773             : 
    4774             :                 /* empty array, if any, and newarraydatum are short-lived */
    4775          13 :                 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4776             : 
    4777          13 :                 if (oldarrayisnull)
    4778           4 :                     oldarraydatum = PointerGetDatum(construct_empty_array(arrayelem->elemtypoid));
    4779             : 
    4780             :                 /*
    4781             :                  * Build the modified array value.
    4782             :                  */
    4783          52 :                 newarraydatum = array_set_element(oldarraydatum,
    4784             :                                                   nsubscripts,
    4785             :                                                   subscriptvals,
    4786             :                                                   coerced_value,
    4787             :                                                   isNull,
    4788          13 :                                                   arrayelem->arraytyplen,
    4789          13 :                                                   arrayelem->elemtyplen,
    4790          13 :                                                   arrayelem->elemtypbyval,
    4791          13 :                                                   arrayelem->elemtypalign);
    4792             : 
    4793          13 :                 MemoryContextSwitchTo(oldcontext);
    4794             : 
    4795             :                 /*
    4796             :                  * Assign the new array to the base variable.  It's never NULL
    4797             :                  * at this point.  Note that if the target is a domain,
    4798             :                  * coercing the base array type back up to the domain will
    4799             :                  * happen within exec_assign_value.
    4800             :                  */
    4801          13 :                 exec_assign_value(estate, target,
    4802             :                                   newarraydatum,
    4803             :                                   false,
    4804             :                                   arrayelem->arraytypoid,
    4805             :                                   arrayelem->arraytypmod);
    4806          11 :                 break;
    4807             :             }
    4808             : 
    4809             :         default:
    4810           0 :             elog(ERROR, "unrecognized dtype: %d", target->dtype);
    4811             :     }
    4812             : }
    4813             : 
    4814             : /*
    4815             :  * exec_eval_datum              Get current value of a PLpgSQL_datum
    4816             :  *
    4817             :  * The type oid, typmod, value in Datum format, and null flag are returned.
    4818             :  *
    4819             :  * At present this doesn't handle PLpgSQL_expr or PLpgSQL_arrayelem datums;
    4820             :  * that's not needed because we never pass references to such datums to SPI.
    4821             :  *
    4822             :  * NOTE: the returned Datum points right at the stored value in the case of
    4823             :  * pass-by-reference datatypes.  Generally callers should take care not to
    4824             :  * modify the stored value.  Some callers intentionally manipulate variables
    4825             :  * referenced by R/W expanded pointers, though; it is those callers'
    4826             :  * responsibility that the results are semantically OK.
    4827             :  *
    4828             :  * In some cases we have to palloc a return value, and in such cases we put
    4829             :  * it into the estate's eval_mcontext.
    4830             :  */
    4831             : static void
    4832        5796 : exec_eval_datum(PLpgSQL_execstate *estate,
    4833             :                 PLpgSQL_datum *datum,
    4834             :                 Oid *typeid,
    4835             :                 int32 *typetypmod,
    4836             :                 Datum *value,
    4837             :                 bool *isnull)
    4838             : {
    4839             :     MemoryContext oldcontext;
    4840             : 
    4841        5796 :     switch (datum->dtype)
    4842             :     {
    4843             :         case PLPGSQL_DTYPE_VAR:
    4844             :             {
    4845         205 :                 PLpgSQL_var *var = (PLpgSQL_var *) datum;
    4846             : 
    4847         205 :                 *typeid = var->datatype->typoid;
    4848         205 :                 *typetypmod = var->datatype->atttypmod;
    4849         205 :                 *value = var->value;
    4850         205 :                 *isnull = var->isnull;
    4851         205 :                 break;
    4852             :             }
    4853             : 
    4854             :         case PLPGSQL_DTYPE_ROW:
    4855             :             {
    4856          45 :                 PLpgSQL_row *row = (PLpgSQL_row *) datum;
    4857             :                 HeapTuple   tup;
    4858             : 
    4859          45 :                 if (!row->rowtupdesc)    /* should not happen */
    4860           0 :                     elog(ERROR, "row variable has no tupdesc");
    4861             :                 /* Make sure we have a valid type/typmod setting */
    4862          45 :                 BlessTupleDesc(row->rowtupdesc);
    4863          45 :                 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4864          45 :                 tup = make_tuple_from_row(estate, row, row->rowtupdesc);
    4865          45 :                 if (tup == NULL)    /* should not happen */
    4866           0 :                     elog(ERROR, "row not compatible with its own tupdesc");
    4867          45 :                 *typeid = row->rowtupdesc->tdtypeid;
    4868          45 :                 *typetypmod = row->rowtupdesc->tdtypmod;
    4869          45 :                 *value = HeapTupleGetDatum(tup);
    4870          45 :                 *isnull = false;
    4871          45 :                 MemoryContextSwitchTo(oldcontext);
    4872          45 :                 break;
    4873             :             }
    4874             : 
    4875             :         case PLPGSQL_DTYPE_REC:
    4876             :             {
    4877         105 :                 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
    4878             : 
    4879         105 :                 if (!HeapTupleIsValid(rec->tup))
    4880           0 :                     ereport(ERROR,
    4881             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    4882             :                              errmsg("record \"%s\" is not assigned yet",
    4883             :                                     rec->refname),
    4884             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    4885         105 :                 Assert(rec->tupdesc != NULL);
    4886             :                 /* Make sure we have a valid type/typmod setting */
    4887         105 :                 BlessTupleDesc(rec->tupdesc);
    4888             : 
    4889         105 :                 oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    4890         105 :                 *typeid = rec->tupdesc->tdtypeid;
    4891         105 :                 *typetypmod = rec->tupdesc->tdtypmod;
    4892         105 :                 *value = heap_copy_tuple_as_datum(rec->tup, rec->tupdesc);
    4893         105 :                 *isnull = false;
    4894         105 :                 MemoryContextSwitchTo(oldcontext);
    4895         105 :                 break;
    4896             :             }
    4897             : 
    4898             :         case PLPGSQL_DTYPE_RECFIELD:
    4899             :             {
    4900        5441 :                 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
    4901             :                 PLpgSQL_rec *rec;
    4902             :                 int         fno;
    4903             : 
    4904        5441 :                 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
    4905        5441 :                 if (!HeapTupleIsValid(rec->tup))
    4906           0 :                     ereport(ERROR,
    4907             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    4908             :                              errmsg("record \"%s\" is not assigned yet",
    4909             :                                     rec->refname),
    4910             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    4911        5441 :                 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
    4912        5441 :                 if (fno == SPI_ERROR_NOATTRIBUTE)
    4913           0 :                     ereport(ERROR,
    4914             :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
    4915             :                              errmsg("record \"%s\" has no field \"%s\"",
    4916             :                                     rec->refname, recfield->fieldname)));
    4917        5441 :                 *typeid = SPI_gettypeid(rec->tupdesc, fno);
    4918        5441 :                 if (fno > 0)
    4919             :                 {
    4920        5441 :                     Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
    4921             : 
    4922        5441 :                     *typetypmod = attr->atttypmod;
    4923             :                 }
    4924             :                 else
    4925           0 :                     *typetypmod = -1;
    4926        5441 :                 *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
    4927        5441 :                 break;
    4928             :             }
    4929             : 
    4930             :         default:
    4931           0 :             elog(ERROR, "unrecognized dtype: %d", datum->dtype);
    4932             :     }
    4933        5796 : }
    4934             : 
    4935             : /*
    4936             :  * plpgsql_exec_get_datum_type              Get datatype of a PLpgSQL_datum
    4937             :  *
    4938             :  * This is the same logic as in exec_eval_datum, except that it can handle
    4939             :  * some cases where exec_eval_datum has to fail; specifically, we may have
    4940             :  * a tupdesc but no row value for a record variable.  (This currently can
    4941             :  * happen only for a trigger's NEW/OLD records.)
    4942             :  */
    4943             : Oid
    4944          10 : plpgsql_exec_get_datum_type(PLpgSQL_execstate *estate,
    4945             :                             PLpgSQL_datum *datum)
    4946             : {
    4947             :     Oid         typeid;
    4948             : 
    4949          10 :     switch (datum->dtype)
    4950             :     {
    4951             :         case PLPGSQL_DTYPE_VAR:
    4952             :             {
    4953          10 :                 PLpgSQL_var *var = (PLpgSQL_var *) datum;
    4954             : 
    4955          10 :                 typeid = var->datatype->typoid;
    4956          10 :                 break;
    4957             :             }
    4958             : 
    4959             :         case PLPGSQL_DTYPE_ROW:
    4960             :             {
    4961           0 :                 PLpgSQL_row *row = (PLpgSQL_row *) datum;
    4962             : 
    4963           0 :                 if (!row->rowtupdesc)    /* should not happen */
    4964           0 :                     elog(ERROR, "row variable has no tupdesc");
    4965             :                 /* Make sure we have a valid type/typmod setting */
    4966           0 :                 BlessTupleDesc(row->rowtupdesc);
    4967           0 :                 typeid = row->rowtupdesc->tdtypeid;
    4968           0 :                 break;
    4969             :             }
    4970             : 
    4971             :         case PLPGSQL_DTYPE_REC:
    4972             :             {
    4973           0 :                 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
    4974             : 
    4975           0 :                 if (rec->tupdesc == NULL)
    4976           0 :                     ereport(ERROR,
    4977             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    4978             :                              errmsg("record \"%s\" is not assigned yet",
    4979             :                                     rec->refname),
    4980             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    4981             :                 /* Make sure we have a valid type/typmod setting */
    4982           0 :                 BlessTupleDesc(rec->tupdesc);
    4983           0 :                 typeid = rec->tupdesc->tdtypeid;
    4984           0 :                 break;
    4985             :             }
    4986             : 
    4987             :         case PLPGSQL_DTYPE_RECFIELD:
    4988             :             {
    4989           0 :                 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
    4990             :                 PLpgSQL_rec *rec;
    4991             :                 int         fno;
    4992             : 
    4993           0 :                 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
    4994           0 :                 if (rec->tupdesc == NULL)
    4995           0 :                     ereport(ERROR,
    4996             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    4997             :                              errmsg("record \"%s\" is not assigned yet",
    4998             :                                     rec->refname),
    4999             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    5000           0 :                 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
    5001           0 :                 if (fno == SPI_ERROR_NOATTRIBUTE)
    5002           0 :                     ereport(ERROR,
    5003             :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
    5004             :                              errmsg("record \"%s\" has no field \"%s\"",
    5005             :                                     rec->refname, recfield->fieldname)));
    5006           0 :                 typeid = SPI_gettypeid(rec->tupdesc, fno);
    5007           0 :                 break;
    5008             :             }
    5009             : 
    5010             :         default:
    5011           0 :             elog(ERROR, "unrecognized dtype: %d", datum->dtype);
    5012             :             typeid = InvalidOid;    /* keep compiler quiet */
    5013             :             break;
    5014             :     }
    5015             : 
    5016          10 :     return typeid;
    5017             : }
    5018             : 
    5019             : /*
    5020             :  * plpgsql_exec_get_datum_type_info         Get datatype etc of a PLpgSQL_datum
    5021             :  *
    5022             :  * An extended version of plpgsql_exec_get_datum_type, which also retrieves the
    5023             :  * typmod and collation of the datum.
    5024             :  */
    5025             : void
    5026        1911 : plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate,
    5027             :                                  PLpgSQL_datum *datum,
    5028             :                                  Oid *typeid, int32 *typmod, Oid *collation)
    5029             : {
    5030        1911 :     switch (datum->dtype)
    5031             :     {
    5032             :         case PLPGSQL_DTYPE_VAR:
    5033             :             {
    5034        1395 :                 PLpgSQL_var *var = (PLpgSQL_var *) datum;
    5035             : 
    5036        1395 :                 *typeid = var->datatype->typoid;
    5037        1395 :                 *typmod = var->datatype->atttypmod;
    5038        1395 :                 *collation = var->datatype->collation;
    5039        1395 :                 break;
    5040             :             }
    5041             : 
    5042             :         case PLPGSQL_DTYPE_ROW:
    5043             :             {
    5044           5 :                 PLpgSQL_row *row = (PLpgSQL_row *) datum;
    5045             : 
    5046           5 :                 if (!row->rowtupdesc)    /* should not happen */
    5047           0 :                     elog(ERROR, "row variable has no tupdesc");
    5048             :                 /* Make sure we have a valid type/typmod setting */
    5049           5 :                 BlessTupleDesc(row->rowtupdesc);
    5050           5 :                 *typeid = row->rowtupdesc->tdtypeid;
    5051             :                 /* do NOT return the mutable typmod of a RECORD variable */
    5052           5 :                 *typmod = -1;
    5053             :                 /* composite types are never collatable */
    5054           5 :                 *collation = InvalidOid;
    5055           5 :                 break;
    5056             :             }
    5057             : 
    5058             :         case PLPGSQL_DTYPE_REC:
    5059             :             {
    5060          25 :                 PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
    5061             : 
    5062          25 :                 if (rec->tupdesc == NULL)
    5063           0 :                     ereport(ERROR,
    5064             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    5065             :                              errmsg("record \"%s\" is not assigned yet",
    5066             :                                     rec->refname),
    5067             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    5068             :                 /* Make sure we have a valid type/typmod setting */
    5069          25 :                 BlessTupleDesc(rec->tupdesc);
    5070          25 :                 *typeid = rec->tupdesc->tdtypeid;
    5071             :                 /* do NOT return the mutable typmod of a RECORD variable */
    5072          25 :                 *typmod = -1;
    5073             :                 /* composite types are never collatable */
    5074          25 :                 *collation = InvalidOid;
    5075          25 :                 break;
    5076             :             }
    5077             : 
    5078             :         case PLPGSQL_DTYPE_RECFIELD:
    5079             :             {
    5080         486 :                 PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
    5081             :                 PLpgSQL_rec *rec;
    5082             :                 int         fno;
    5083             : 
    5084         486 :                 rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
    5085         486 :                 if (rec->tupdesc == NULL)
    5086           0 :                     ereport(ERROR,
    5087             :                             (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    5088             :                              errmsg("record \"%s\" is not assigned yet",
    5089             :                                     rec->refname),
    5090             :                              errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
    5091         486 :                 fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
    5092         486 :                 if (fno == SPI_ERROR_NOATTRIBUTE)
    5093           0 :                     ereport(ERROR,
    5094             :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
    5095             :                              errmsg("record \"%s\" has no field \"%s\"",
    5096             :                                     rec->refname, recfield->fieldname)));
    5097         486 :                 *typeid = SPI_gettypeid(rec->tupdesc, fno);
    5098         486 :                 if (fno > 0)
    5099             :                 {
    5100         486 :                     Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
    5101             : 
    5102         486 :                     *typmod = attr->atttypmod;
    5103             :                 }
    5104             :                 else
    5105           0 :                     *typmod = -1;
    5106         486 :                 if (fno > 0)
    5107             :                 {
    5108         486 :                     Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1);
    5109             : 
    5110         486 :                     *collation = attr->attcollation;
    5111             :                 }
    5112             :                 else            /* no system column types have collation */
    5113           0 :                     *collation = InvalidOid;
    5114         486 :                 break;
    5115             :             }
    5116             : 
    5117             :         default:
    5118           0 :             elog(ERROR, "unrecognized dtype: %d", datum->dtype);
    5119             :             *typeid = InvalidOid;   /* keep compiler quiet */
    5120             :             *typmod = -1;
    5121             :             *collation = InvalidOid;
    5122             :             break;
    5123             :     }
    5124        1911 : }
    5125             : 
    5126             : /* ----------
    5127             :  * exec_eval_integer        Evaluate an expression, coerce result to int4
    5128             :  *
    5129             :  * Note we do not do exec_eval_cleanup here; the caller must do it at
    5130             :  * some later point.  (We do this because the caller may be holding the
    5131             :  * results of other, pass-by-reference, expression evaluations, such as
    5132             :  * an array value to be subscripted.)
    5133             :  * ----------
    5134             :  */
    5135             : static int
    5136          28 : exec_eval_integer(PLpgSQL_execstate *estate,
    5137             :                   PLpgSQL_expr *expr,
    5138             :                   bool *isNull)
    5139             : {
    5140             :     Datum       exprdatum;
    5141             :     Oid         exprtypeid;
    5142             :     int32       exprtypmod;
    5143             : 
    5144          28 :     exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
    5145          28 :     exprdatum = exec_cast_value(estate, exprdatum, isNull,
    5146             :                                 exprtypeid, exprtypmod,
    5147             :                                 INT4OID, -1);
    5148          28 :     return DatumGetInt32(exprdatum);
    5149             : }
    5150             : 
    5151             : /* ----------
    5152             :  * exec_eval_boolean        Evaluate an expression, coerce result to bool
    5153             :  *
    5154             :  * Note we do not do exec_eval_cleanup here; the caller must do it at
    5155             :  * some later point.
    5156             :  * ----------
    5157             :  */
    5158             : static bool
    5159       14819 : exec_eval_boolean(PLpgSQL_execstate *estate,
    5160             :                   PLpgSQL_expr *expr,
    5161             :                   bool *isNull)
    5162             : {
    5163             :     Datum       exprdatum;
    5164             :     Oid         exprtypeid;
    5165             :     int32       exprtypmod;
    5166             : 
    5167       14819 :     exprdatum = exec_eval_expr(estate, expr, isNull, &exprtypeid, &exprtypmod);
    5168       14819 :     exprdatum = exec_cast_value(estate, exprdatum, isNull,
    5169             :                                 exprtypeid, exprtypmod,
    5170             :                                 BOOLOID, -1);
    5171       14819 :     return DatumGetBool(exprdatum);
    5172             : }
    5173             : 
    5174             : /* ----------
    5175             :  * exec_eval_expr           Evaluate an expression and return
    5176             :  *                  the result Datum, along with data type/typmod.
    5177             :  *
    5178             :  * NOTE: caller must do exec_eval_cleanup when done with the Datum.
    5179             :  * ----------
    5180             :  */
    5181             : static Datum
    5182       27855 : exec_eval_expr(PLpgSQL_execstate *estate,
    5183             :                PLpgSQL_expr *expr,
    5184             :                bool *isNull,
    5185             :                Oid *rettype,
    5186             :                int32 *rettypmod)
    5187             : {
    5188       27855 :     Datum       result = 0;
    5189             :     int         rc;
    5190             :     Form_pg_attribute attr;
    5191             : 
    5192             :     /*
    5193             :      * If first time through, create a plan for this expression.
    5194             :      */
    5195       27855 :     if (expr->plan == NULL)
    5196        1101 :         exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
    5197             : 
    5198             :     /*
    5199             :      * If this is a simple expression, bypass SPI and use the executor
    5200             :      * directly
    5201             :      */
    5202       27851 :     if (exec_eval_simple_expr(estate, expr,
    5203             :                               &result, isNull, rettype, rettypmod))
    5204       27127 :         return result;
    5205             : 
    5206             :     /*
    5207             :      * Else do it the hard way via exec_run_select
    5208             :      */
    5209         703 :     rc = exec_run_select(estate, expr, 2, NULL);
    5210         701 :     if (rc != SPI_OK_SELECT)
    5211           0 :         ereport(ERROR,
    5212             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    5213             :                  errmsg("query \"%s\" did not return data", expr->query)));
    5214             : 
    5215             :     /*
    5216             :      * Check that the expression returns exactly one column...
    5217             :      */
    5218         701 :     if (estate->eval_tuptable->tupdesc->natts != 1)
    5219           0 :         ereport(ERROR,
    5220             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    5221             :                  errmsg_plural("query \"%s\" returned %d column",
    5222             :                                "query \"%s\" returned %d columns",
    5223             :                                estate->eval_tuptable->tupdesc->natts,
    5224             :                                expr->query,
    5225             :                                estate->eval_tuptable->tupdesc->natts)));
    5226             : 
    5227             :     /*
    5228             :      * ... and get the column's datatype.
    5229             :      */
    5230         701 :     attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0);
    5231         701 :     *rettype = attr->atttypid;
    5232         701 :     *rettypmod = attr->atttypmod;
    5233             : 
    5234             :     /*
    5235             :      * If there are no rows selected, the result is a NULL of that type.
    5236             :      */
    5237         701 :     if (estate->eval_processed == 0)
    5238             :     {
    5239           0 :         *isNull = true;
    5240           0 :         return (Datum) 0;
    5241             :     }
    5242             : 
    5243             :     /*
    5244             :      * Check that the expression returned no more than one row.
    5245             :      */
    5246         701 :     if (estate->eval_processed != 1)
    5247           0 :         ereport(ERROR,
    5248             :                 (errcode(ERRCODE_CARDINALITY_VIOLATION),
    5249             :                  errmsg("query \"%s\" returned more than one row",
    5250             :                         expr->query)));
    5251             : 
    5252             :     /*
    5253             :      * Return the single result Datum.
    5254             :      */
    5255         701 :     return SPI_getbinval(estate->eval_tuptable->vals[0],
    5256         701 :                          estate->eval_tuptable->tupdesc, 1, isNull);
    5257             : }
    5258             : 
    5259             : 
    5260             : /* ----------
    5261             :  * exec_run_select          Execute a select query
    5262             :  * ----------
    5263             :  */
    5264             : static int
    5265        1130 : exec_run_select(PLpgSQL_execstate *estate,
    5266             :                 PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
    5267             : {
    5268             :     ParamListInfo paramLI;
    5269             :     int         rc;
    5270             : 
    5271             :     /*
    5272             :      * On the first call for this expression generate the plan.
    5273             :      *
    5274             :      * If we don't need to return a portal, then we're just going to execute
    5275             :      * the query once, which means it's OK to use a parallel plan, even if the
    5276             :      * number of rows being fetched is limited.  If we do need to return a
    5277             :      * portal, the caller might do cursor operations, which parallel query
    5278             :      * can't support.
    5279             :      */
    5280        1130 :     if (expr->plan == NULL)
    5281          54 :         exec_prepare_plan(estate, expr,
    5282             :                           portalP == NULL ? CURSOR_OPT_PARALLEL_OK : 0);
    5283             : 
    5284             :     /*
    5285             :      * If a portal was requested, put the query into the portal
    5286             :      */
    5287        1125 :     if (portalP != NULL)
    5288             :     {
    5289             :         /*
    5290             :          * Set up short-lived ParamListInfo
    5291             :          */
    5292         189 :         paramLI = setup_unshared_param_list(estate, expr);
    5293             : 
    5294         189 :         *portalP = SPI_cursor_open_with_paramlist(NULL, expr->plan,
    5295             :                                                   paramLI,
    5296         189 :                                                   estate->readonly_func);
    5297         189 :         if (*portalP == NULL)
    5298           0 :             elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
    5299             :                  expr->query, SPI_result_code_string(SPI_result));
    5300         189 :         exec_eval_cleanup(estate);
    5301         189 :         return SPI_OK_CURSOR;
    5302             :     }
    5303             : 
    5304             :     /*
    5305             :      * Set up ParamListInfo to pass to executor
    5306             :      */
    5307         936 :     paramLI = setup_param_list(estate, expr);
    5308             : 
    5309             :     /*
    5310             :      * Execute the query
    5311             :      */
    5312         936 :     rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
    5313         936 :                                          estate->readonly_func, maxtuples);
    5314         729 :     if (rc != SPI_OK_SELECT)
    5315           0 :         ereport(ERROR,
    5316             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    5317             :                  errmsg("query \"%s\" is not a SELECT", expr->query)));
    5318             : 
    5319             :     /* Save query results for eventual cleanup */
    5320         729 :     Assert(estate->eval_tuptable == NULL);
    5321         729 :     estate->eval_tuptable = SPI_tuptable;
    5322         729 :     estate->eval_processed = SPI_processed;
    5323         729 :     estate->eval_lastoid = SPI_lastoid;
    5324             : 
    5325         729 :     return rc;
    5326             : }
    5327             : 
    5328             : 
    5329             : /*
    5330             :  * exec_for_query --- execute body of FOR loop for each row from a portal
    5331             :  *
    5332             :  * Used by exec_stmt_fors, exec_stmt_forc and exec_stmt_dynfors
    5333             :  */
    5334             : static int
    5335         681 : exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
    5336             :                Portal portal, bool prefetch_ok)
    5337             : {
    5338         681 :     PLpgSQL_rec *rec = NULL;
    5339         681 :     PLpgSQL_row *row = NULL;
    5340             :     SPITupleTable *tuptab;
    5341         681 :     bool        found = false;
    5342         681 :     int         rc = PLPGSQL_RC_OK;
    5343             :     uint64      n;
    5344             : 
    5345             :     /*
    5346             :      * Determine if we assign to a record or a row
    5347             :      */
    5348         681 :     if (stmt->rec != NULL)
    5349          42 :         rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
    5350         639 :     else if (stmt->row != NULL)
    5351         639 :         row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
    5352             :     else
    5353           0 :         elog(ERROR, "unsupported target");
    5354             : 
    5355             :     /*
    5356             :      * Make sure the portal doesn't get closed by the user statements we
    5357             :      * execute.
    5358             :      */
    5359         681 :     PinPortal(portal);
    5360             : 
    5361             :     /*
    5362             :      * Fetch the initial tuple(s).  If prefetching is allowed then we grab a
    5363             :      * few more rows to avoid multiple trips through executor startup
    5364             :      * overhead.
    5365             :      */
    5366         681 :     SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1);
    5367         681 :     tuptab = SPI_tuptable;
    5368         681 :     n = SPI_processed;
    5369             : 
    5370             :     /*
    5371             :      * If the query didn't return any rows, set the target to NULL and fall
    5372             :      * through with found = false.
    5373             :      */
    5374         681 :     if (n == 0)
    5375             :     {
    5376           5 :         exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
    5377           5 :         exec_eval_cleanup(estate);
    5378             :     }
    5379             :     else
    5380         676 :         found = true;           /* processed at least one tuple */
    5381             : 
    5382             :     /*
    5383             :      * Now do the loop
    5384             :      */
    5385        2063 :     while (n > 0)
    5386             :     {
    5387             :         uint64      i;
    5388             : 
    5389        3525 :         for (i = 0; i < n; i++)
    5390             :         {
    5391             :             /*
    5392             :              * Assign the tuple to the target
    5393             :              */
    5394        2824 :             exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
    5395        2824 :             exec_eval_cleanup(estate);
    5396             : 
    5397             :             /*
    5398             :              * Execute the statements
    5399             :              */
    5400        2824 :             rc = exec_stmts(estate, stmt->body);
    5401             : 
    5402        2821 :             if (rc != PLPGSQL_RC_OK)
    5403             :             {
    5404          38 :                 if (rc == PLPGSQL_RC_EXIT)
    5405             :                 {
    5406           0 :                     if (estate->exitlabel == NULL)
    5407             :                     {
    5408             :                         /* unlabelled exit, so exit the current loop */
    5409           0 :                         rc = PLPGSQL_RC_OK;
    5410             :                     }
    5411           0 :                     else if (stmt->label != NULL &&
    5412           0 :                              strcmp(stmt->label, estate->exitlabel) == 0)
    5413             :                     {
    5414             :                         /* label matches this loop, so exit loop */
    5415           0 :                         estate->exitlabel = NULL;
    5416           0 :                         rc = PLPGSQL_RC_OK;
    5417             :                     }
    5418             : 
    5419             :                     /*
    5420             :                      * otherwise, we processed a labelled exit that does not
    5421             :                      * match the current statement's label, if any; return
    5422             :                      * RC_EXIT so that the EXIT continues to recurse upward.
    5423             :                      */
    5424             :                 }
    5425          38 :                 else if (rc == PLPGSQL_RC_CONTINUE)
    5426             :                 {
    5427          38 :                     if (estate->exitlabel == NULL)
    5428             :                     {
    5429             :                         /* unlabelled continue, so re-run the current loop */
    5430          38 :                         rc = PLPGSQL_RC_OK;
    5431          38 :                         continue;
    5432             :                     }
    5433           0 :                     else if (stmt->label != NULL &&
    5434           0 :                              strcmp(stmt->label, estate->exitlabel) == 0)
    5435             :                     {
    5436             :                         /* label matches this loop, so re-run loop */
    5437           0 :                         estate->exitlabel = NULL;
    5438           0 :                         rc = PLPGSQL_RC_OK;
    5439           0 :                         continue;
    5440             :                     }
    5441             : 
    5442             :                     /*
    5443             :                      * otherwise, we process a labelled continue that does not
    5444             :                      * match the current statement's label, if any; return
    5445             :                      * RC_CONTINUE so that the CONTINUE will propagate up the
    5446             :                      * stack.
    5447             :                      */
    5448             :                 }
    5449             : 
    5450             :                 /*
    5451             :                  * We're aborting the loop.  Need a goto to get out of two
    5452             :                  * levels of loop...
    5453             :                  */
    5454           0 :                 goto loop_exit;
    5455             :             }
    5456             :         }
    5457             : 
    5458         701 :         SPI_freetuptable(tuptab);
    5459             : 
    5460             :         /*
    5461             :          * Fetch more tuples.  If prefetching is allowed, grab 50 at a time.
    5462             :          */
    5463         701 :         SPI_cursor_fetch(portal, true, prefetch_ok ? 50 : 1);
    5464         701 :         tuptab = SPI_tuptable;
    5465         701 :         n = SPI_processed;
    5466             :     }
    5467             : 
    5468             : loop_exit:
    5469             : 
    5470             :     /*
    5471             :      * Release last group of tuples (if any)
    5472             :      */
    5473         678 :     SPI_freetuptable(tuptab);
    5474             : 
    5475         678 :     UnpinPortal(portal);
    5476             : 
    5477             :     /*
    5478             :      * Set the FOUND variable to indicate the result of executing the loop
    5479             :      * (namely, whether we looped one or more times). This must be set last so
    5480             :      * that it does not interfere with the value of the FOUND variable inside
    5481             :      * the loop processing itself.
    5482             :      */
    5483         678 :     exec_set_found(estate, found);
    5484             : 
    5485         678 :     return rc;
    5486             : }
    5487             : 
    5488             : 
    5489             : /* ----------
    5490             :  * exec_eval_simple_expr -      Evaluate a simple expression returning
    5491             :  *                              a Datum by directly calling ExecEvalExpr().
    5492             :  *
    5493             :  * If successful, store results into *result, *isNull, *rettype, *rettypmod
    5494             :  * and return TRUE.  If the expression cannot be handled by simple evaluation,
    5495             :  * return FALSE.
    5496             :  *
    5497             :  * Because we only store one execution tree for a simple expression, we
    5498             :  * can't handle recursion cases.  So, if we see the tree is already busy
    5499             :  * with an evaluation in the current xact, we just return FALSE and let the
    5500             :  * caller run the expression the hard way.  (Other alternatives such as
    5501             :  * creating a new tree for a recursive call either introduce memory leaks,
    5502             :  * or add enough bookkeeping to be doubtful wins anyway.)  Another case that
    5503             :  * is covered by the expr_simple_in_use test is where a previous execution
    5504             :  * of the tree was aborted by an error: the tree may contain bogus state
    5505             :  * so we dare not re-use it.
    5506             :  *
    5507             :  * It is possible that we'd need to replan a simple expression; for example,
    5508             :  * someone might redefine a SQL function that had been inlined into the simple
    5509             :  * expression.  That cannot cause a simple expression to become non-simple (or
    5510             :  * vice versa), but we do have to handle replacing the expression tree.
    5511             :  * Fortunately it's normally inexpensive to call SPI_plan_get_cached_plan for
    5512             :  * a simple expression.
    5513             :  *
    5514             :  * Note: if pass-by-reference, the result is in the eval_mcontext.
    5515             :  * It will be freed when exec_eval_cleanup is done.
    5516             :  * ----------
    5517             :  */
    5518             : static bool
    5519       27851 : exec_eval_simple_expr(PLpgSQL_execstate *estate,
    5520             :                       PLpgSQL_expr *expr,
    5521             :                       Datum *result,
    5522             :                       bool *isNull,
    5523             :                       Oid *rettype,
    5524             :                       int32 *rettypmod)
    5525             : {
    5526       27851 :     ExprContext *econtext = estate->eval_econtext;
    5527       27851 :     LocalTransactionId curlxid = MyProc->lxid;
    5528             :     CachedPlan *cplan;
    5529             :     ParamListInfo paramLI;
    5530             :     void       *save_setup_arg;
    5531             :     MemoryContext oldcontext;
    5532             : 
    5533             :     /*
    5534             :      * Forget it if expression wasn't simple before.
    5535             :      */
    5536       27851 :     if (expr->expr_simple_expr == NULL)
    5537         684 :         return false;
    5538             : 
    5539             :     /*
    5540             :      * If expression is in use in current xact, don't touch it.
    5541             :      */
    5542       27167 :     if (expr->expr_simple_in_use && expr->expr_simple_lxid == curlxid)
    5543          19 :         return false;
    5544             : 
    5545             :     /*
    5546             :      * Revalidate cached plan, so that we will notice if it became stale. (We
    5547             :      * need to hold a refcount while using the plan, anyway.)  If replanning
    5548             :      * is needed, do that work in the eval_mcontext.
    5549             :      */
    5550       27148 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    5551       27148 :     cplan = SPI_plan_get_cached_plan(expr->plan);
    5552       27148 :     MemoryContextSwitchTo(oldcontext);
    5553             : 
    5554             :     /*
    5555             :      * We can't get a failure here, because the number of CachedPlanSources in
    5556             :      * the SPI plan can't change from what exec_simple_check_plan saw; it's a
    5557             :      * property of the raw parsetree generated from the query text.
    5558             :      */
    5559       27148 :     Assert(cplan != NULL);
    5560             : 
    5561             :     /* If it got replanned, update our copy of the simple expression */
    5562       27148 :     if (cplan->generation != expr->expr_simple_generation)
    5563             :     {
    5564         509 :         exec_save_simple_expr(expr, cplan);
    5565             :         /* better recheck r/w safety, as it could change due to inlining */
    5566         509 :         if (expr->rwparam >= 0)
    5567           0 :             exec_check_rw_parameter(expr, expr->rwparam);
    5568             :     }
    5569             : 
    5570             :     /*
    5571             :      * Pass back previously-determined result type.
    5572             :      */
    5573       27148 :     *rettype = expr->expr_simple_type;
    5574       27148 :     *rettypmod = expr->expr_simple_typmod;
    5575             : 
    5576             :     /*
    5577             :      * Prepare the expression for execution, if it's not been done already in
    5578             :      * the current transaction.  (This will be forced to happen if we called
    5579             :      * exec_save_simple_expr above.)
    5580             :      */
    5581       27148 :     if (expr->expr_simple_lxid != curlxid)
    5582             :     {
    5583        6122 :         oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
    5584        6122 :         expr->expr_simple_state = ExecInitExpr(expr->expr_simple_expr, NULL);
    5585        6122 :         expr->expr_simple_in_use = false;
    5586        6122 :         expr->expr_simple_lxid = curlxid;
    5587        6122 :         MemoryContextSwitchTo(oldcontext);
    5588             :     }
    5589             : 
    5590             :     /*
    5591             :      * We have to do some of the things SPI_execute_plan would do, in
    5592             :      * particular advance the snapshot if we are in a non-read-only function.
    5593             :      * Without this, stable functions within the expression would fail to see
    5594             :      * updates made so far by our own function.
    5595             :      */
    5596       27148 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    5597       27148 :     if (!estate->readonly_func)
    5598             :     {
    5599       15152 :         CommandCounterIncrement();
    5600       15152 :         PushActiveSnapshot(GetTransactionSnapshot());
    5601             :     }
    5602             : 
    5603             :     /*
    5604             :      * Set up ParamListInfo to pass to executor.  We need an unshared list if
    5605             :      * it's going to include any R/W expanded-object pointer.  For safety,
    5606             :      * save and restore estate->paramLI->parserSetupArg around our use of the
    5607             :      * param list.
    5608             :      */
    5609       27148 :     save_setup_arg = estate->paramLI->parserSetupArg;
    5610             : 
    5611       27148 :     if (expr->rwparam >= 0)
    5612           0 :         paramLI = setup_unshared_param_list(estate, expr);
    5613             :     else
    5614       27148 :         paramLI = setup_param_list(estate, expr);
    5615             : 
    5616       27148 :     econtext->ecxt_param_list_info = paramLI;
    5617             : 
    5618             :     /*
    5619             :      * Mark expression as busy for the duration of the ExecEvalExpr call.
    5620             :      */
    5621       27148 :     expr->expr_simple_in_use = true;
    5622             : 
    5623             :     /*
    5624             :      * Finally we can call the executor to evaluate the expression
    5625             :      */
    5626       27148 :     *result = ExecEvalExpr(expr->expr_simple_state,
    5627             :                            econtext,
    5628             :                            isNull);
    5629             : 
    5630             :     /* Assorted cleanup */
    5631       27127 :     expr->expr_simple_in_use = false;
    5632             : 
    5633       27127 :     econtext->ecxt_param_list_info = NULL;
    5634             : 
    5635       27127 :     estate->paramLI->parserSetupArg = save_setup_arg;
    5636             : 
    5637       27127 :     if (!estate->readonly_func)
    5638       15131 :         PopActiveSnapshot();
    5639             : 
    5640       27127 :     MemoryContextSwitchTo(oldcontext);
    5641             : 
    5642             :     /*
    5643             :      * Now we can release our refcount on the cached plan.
    5644             :      */
    5645       27127 :     ReleaseCachedPlan(cplan, true);
    5646             : 
    5647             :     /*
    5648             :      * That's it.
    5649             :      */
    5650       27127 :     return true;
    5651             : }
    5652             : 
    5653             : 
    5654             : /*
    5655             :  * Create a ParamListInfo to pass to SPI
    5656             :  *
    5657             :  * We share a single ParamListInfo array across all SPI calls made from this
    5658             :  * estate, except calls creating cursors, which use setup_unshared_param_list
    5659             :  * (see its comments for reasons why), and calls that pass a R/W expanded
    5660             :  * object pointer.  A shared array is generally OK since any given slot in
    5661             :  * the array would need to contain the same current datum value no matter
    5662             :  * which query or expression we're evaluating; but of course that doesn't
    5663             :  * hold when a specific variable is being passed as a R/W pointer, because
    5664             :  * other expressions in the same function probably don't want to do that.
    5665             :  *
    5666             :  * Note that paramLI->parserSetupArg points to the specific PLpgSQL_expr
    5667             :  * being evaluated.  This is not an issue for statement-level callers, but
    5668             :  * lower-level callers must save and restore estate->paramLI->parserSetupArg
    5669             :  * just in case there's an active evaluation at an outer call level.
    5670             :  *
    5671             :  * The general plan for passing parameters to SPI is that plain VAR datums
    5672             :  * always have valid images in the shared param list.  This is ensured by
    5673             :  * assign_simple_var(), which also marks those params as PARAM_FLAG_CONST,
    5674             :  * allowing the planner to use those values in custom plans.  However, non-VAR
    5675             :  * datums cannot conveniently be managed that way.  For one thing, they could
    5676             :  * throw errors (for example "no such record field") and we do not want that
    5677             :  * to happen in a part of the expression that might never be evaluated at
    5678             :  * runtime.  For another thing, exec_eval_datum() may return short-lived
    5679             :  * values stored in the estate's eval_mcontext, which will not necessarily
    5680             :  * survive to the next SPI operation.  And for a third thing, ROW
    5681             :  * and RECFIELD datums' values depend on other datums, and we don't have a
    5682             :  * cheap way to track that.  Therefore, param slots for non-VAR datum types
    5683             :  * are always reset here and then filled on-demand by plpgsql_param_fetch().
    5684             :  * We can save a few cycles by not bothering with the reset loop unless at
    5685             :  * least one such param has actually been filled by plpgsql_param_fetch().
    5686             :  */
    5687             : static ParamListInfo
    5688       29992 : setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
    5689             : {
    5690             :     ParamListInfo paramLI;
    5691             : 
    5692             :     /*
    5693             :      * We must have created the SPIPlan already (hence, query text has been
    5694             :      * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
    5695             :      */
    5696       29992 :     Assert(expr->plan != NULL);
    5697             : 
    5698             :     /*
    5699             :      * Expressions with R/W parameters can't use the shared param list.
    5700             :      */
    5701       29992 :     Assert(expr->rwparam == -1);
    5702             : 
    5703             :     /*
    5704             :      * We only need a ParamListInfo if the expression has parameters.  In
    5705             :      * principle we should test with bms_is_empty(), but we use a not-null
    5706             :      * test because it's faster.  In current usage bits are never removed from
    5707             :      * expr->paramnos, only added, so this test is correct anyway.
    5708             :      */
    5709       29992 :     if (expr->paramnos)
    5710             :     {
    5711             :         /* Use the common ParamListInfo */
    5712       21264 :         paramLI = estate->paramLI;
    5713             : 
    5714             :         /*
    5715             :          * If any resettable parameters have been passed to the executor since
    5716             :          * last time, we need to reset those param slots to "invalid", for the
    5717             :          * reasons mentioned in the comment above.
    5718             :          */
    5719       21264 :         if (estate->params_dirty)
    5720             :         {
    5721        2325 :             Bitmapset  *resettable_datums = estate->func->resettable_datums;
    5722        2325 :             int         dno = -1;
    5723             : 
    5724       36557 :             while ((dno = bms_next_member(resettable_datums, dno)) >= 0)
    5725             :             {
    5726       31907 :                 ParamExternData *prm = &paramLI->params[dno];
    5727             : 
    5728       31907 :                 prm->ptype = InvalidOid;
    5729             :             }
    5730        2325 :             estate->params_dirty = false;
    5731             :         }
    5732             : 
    5733             :         /*
    5734             :          * Set up link to active expr where the hook functions can find it.
    5735             :          * Callers must save and restore parserSetupArg if there is any chance
    5736             :          * that they are interrupting an active use of parameters.
    5737             :          */
    5738       21264 :         paramLI->parserSetupArg = (void *) expr;
    5739             : 
    5740             :         /*
    5741             :          * Allow parameters that aren't needed by this expression to be
    5742             :          * ignored.
    5743             :          */
    5744       21264 :         paramLI->paramMask = expr->paramnos;
    5745             : 
    5746             :         /*
    5747             :          * Also make sure this is set before parser hooks need it.  There is
    5748             :          * no need to save and restore, since the value is always correct once
    5749             :          * set.  (Should be set already, but let's be sure.)
    5750             :          */
    5751       21264 :         expr->func = estate->func;
    5752             :     }
    5753             :     else
    5754             :     {
    5755             :         /*
    5756             :          * Expression requires no parameters.  Be sure we represent this case
    5757             :          * as a NULL ParamListInfo, so that plancache.c knows there is no
    5758             :          * point in a custom plan.
    5759             :          */
    5760        8728 :         paramLI = NULL;
    5761             :     }
    5762       29992 :     return paramLI;
    5763             : }
    5764             : 
    5765             : /*
    5766             :  * Create an unshared, short-lived ParamListInfo to pass to SPI
    5767             :  *
    5768             :  * When creating a cursor, we do not use the shared ParamListInfo array
    5769             :  * but create a short-lived one that will contain only params actually
    5770             :  * referenced by the query.  The reason for this is that copyParamList() will
    5771             :  * be used to copy the parameters into cursor-lifespan storage, and we don't
    5772             :  * want it to copy anything that's not used by the specific cursor; that
    5773             :  * could result in uselessly copying some large values.
    5774             :  *
    5775             :  * We also use this for expressions that are passing a R/W object pointer
    5776             :  * to some trusted function.  We don't want the R/W pointer to get into the
    5777             :  * shared param list, where it could get passed to some less-trusted function.
    5778             :  *
    5779             :  * The result, if not NULL, is in the estate's eval_mcontext.
    5780             :  *
    5781             :  * XXX. Could we use ParamListInfo's new paramMask to avoid creating unshared
    5782             :  * parameter lists?
    5783             :  */
    5784             : static ParamListInfo
    5785         210 : setup_unshared_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
    5786             : {
    5787             :     ParamListInfo paramLI;
    5788             : 
    5789             :     /*
    5790             :      * We must have created the SPIPlan already (hence, query text has been
    5791             :      * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
    5792             :      */
    5793         210 :     Assert(expr->plan != NULL);
    5794             : 
    5795             :     /*
    5796             :      * We only need a ParamListInfo if the expression has parameters.  In
    5797             :      * principle we should test with bms_is_empty(), but we use a not-null
    5798             :      * test because it's faster.  In current usage bits are never removed from
    5799             :      * expr->paramnos, only added, so this test is correct anyway.
    5800             :      */
    5801         210 :     if (expr->paramnos)
    5802             :     {
    5803             :         int         dno;
    5804             : 
    5805             :         /* initialize ParamListInfo with one entry per datum, all invalid */
    5806          20 :         paramLI = (ParamListInfo)
    5807          20 :             eval_mcontext_alloc0(estate,
    5808             :                                  offsetof(ParamListInfoData, params) +
    5809             :                                  estate->ndatums * sizeof(ParamExternData));
    5810          20 :         paramLI->paramFetch = plpgsql_param_fetch;
    5811          20 :         paramLI->paramFetchArg = (void *) estate;
    5812          20 :         paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup;
    5813          20 :         paramLI->parserSetupArg = (void *) expr;
    5814          20 :         paramLI->numParams = estate->ndatums;
    5815          20 :         paramLI->paramMask = NULL;
    5816             : 
    5817             :         /*
    5818             :          * Instantiate values for "safe" parameters of the expression.  We
    5819             :          * could skip this and leave them to be filled by plpgsql_param_fetch;
    5820             :          * but then the values would not be available for query planning,
    5821             :          * since the planner doesn't call the paramFetch hook.
    5822             :          */
    5823          20 :         dno = -1;
    5824          70 :         while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
    5825             :         {
    5826          30 :             PLpgSQL_datum *datum = estate->datums[dno];
    5827             : 
    5828          30 :             if (datum->dtype == PLPGSQL_DTYPE_VAR)
    5829             :             {
    5830          30 :                 PLpgSQL_var *var = (PLpgSQL_var *) datum;
    5831          30 :                 ParamExternData *prm = &paramLI->params[dno];
    5832             : 
    5833          30 :                 if (dno == expr->rwparam)
    5834           0 :                     prm->value = var->value;
    5835             :                 else
    5836          30 :                     prm->value = MakeExpandedObjectReadOnly(var->value,
    5837             :                                                             var->isnull,
    5838             :                                                             var->datatype->typlen);
    5839          30 :                 prm->isnull = var->isnull;
    5840          30 :                 prm->pflags = PARAM_FLAG_CONST;
    5841          30 :                 prm->ptype = var->datatype->typoid;
    5842             :             }
    5843             :         }
    5844             : 
    5845             :         /*
    5846             :          * Also make sure this is set before parser hooks need it.  There is
    5847             :          * no need to save and restore, since the value is always correct once
    5848             :          * set.  (Should be set already, but let's be sure.)
    5849             :          */
    5850          20 :         expr->func = estate->func;
    5851             :     }
    5852             :     else
    5853             :     {
    5854             :         /*
    5855             :          * Expression requires no parameters.  Be sure we represent this case
    5856             :          * as a NULL ParamListInfo, so that plancache.c knows there is no
    5857             :          * point in a custom plan.
    5858             :          */
    5859         190 :         paramLI = NULL;
    5860             :     }
    5861         210 :     return paramLI;
    5862             : }
    5863             : 
    5864             : /*
    5865             :  * plpgsql_param_fetch      paramFetch callback for dynamic parameter fetch
    5866             :  */
    5867             : static void
    5868        5697 : plpgsql_param_fetch(ParamListInfo params, int paramid)
    5869             : {
    5870             :     int         dno;
    5871             :     PLpgSQL_execstate *estate;
    5872             :     PLpgSQL_expr *expr;
    5873             :     PLpgSQL_datum *datum;
    5874             :     ParamExternData *prm;
    5875             :     int32       prmtypmod;
    5876             : 
    5877             :     /* paramid's are 1-based, but dnos are 0-based */
    5878        5697 :     dno = paramid - 1;
    5879        5697 :     Assert(dno >= 0 && dno < params->numParams);
    5880             : 
    5881             :     /* fetch back the hook data */
    5882        5697 :     estate = (PLpgSQL_execstate *) params->paramFetchArg;
    5883        5697 :     expr = (PLpgSQL_expr *) params->parserSetupArg;
    5884        5697 :     Assert(params->numParams == estate->ndatums);
    5885             : 
    5886             :     /* now we can access the target datum */
    5887        5697 :     datum = estate->datums[dno];
    5888             : 
    5889             :     /*
    5890             :      * Since copyParamList() or SerializeParamList() will try to materialize
    5891             :      * every single parameter slot, it's important to do nothing when asked
    5892             :      * for a datum that's not supposed to be used by this SQL expression.
    5893             :      * Otherwise we risk failures in exec_eval_datum(), or copying a lot more
    5894             :      * data than necessary.
    5895             :      */
    5896        5697 :     if (!bms_is_member(dno, expr->paramnos))
    5897        5806 :         return;
    5898             : 
    5899        5588 :     if (params == estate->paramLI)
    5900             :     {
    5901             :         /*
    5902             :          * We need to mark the shared params array dirty if we're about to
    5903             :          * evaluate a resettable datum.
    5904             :          */
    5905        5588 :         switch (datum->dtype)
    5906             :         {
    5907             :             case PLPGSQL_DTYPE_ROW:
    5908             :             case PLPGSQL_DTYPE_REC:
    5909             :             case PLPGSQL_DTYPE_RECFIELD:
    5910        5588 :                 estate->params_dirty = true;
    5911        5588 :                 break;
    5912             : 
    5913             :             default:
    5914           0 :                 break;
    5915             :         }
    5916             :     }
    5917             : 
    5918             :     /* OK, evaluate the value and store into the appropriate paramlist slot */
    5919        5588 :     prm = &params->params[dno];
    5920        5588 :     exec_eval_datum(estate, datum,
    5921             :                     &prm->ptype, &prmtypmod,
    5922             :                     &prm->value, &prm->isnull);
    5923             :     /* We can always mark params as "const" for executor's purposes */
    5924        5588 :     prm->pflags = PARAM_FLAG_CONST;
    5925             : 
    5926             :     /*
    5927             :      * If it's a read/write expanded datum, convert reference to read-only,
    5928             :      * unless it's safe to pass as read-write.
    5929             :      */
    5930        5588 :     if (datum->dtype == PLPGSQL_DTYPE_VAR && dno != expr->rwparam)
    5931           0 :         prm->value = MakeExpandedObjectReadOnly(prm->value,
    5932             :                                                 prm->isnull,
    5933             :                                                 ((PLpgSQL_var *) datum)->datatype->typlen);
    5934             : }
    5935             : 
    5936             : 
    5937             : /* ----------
    5938             :  * exec_move_row            Move one tuple's values into a record or row
    5939             :  *
    5940             :  * Since this uses exec_assign_value, caller should eventually call
    5941             :  * exec_eval_cleanup to prevent long-term memory leaks.
    5942             :  * ----------
    5943             :  */
    5944             : static void
    5945        4072 : exec_move_row(PLpgSQL_execstate *estate,
    5946             :               PLpgSQL_rec *rec,
    5947             :               PLpgSQL_row *row,
    5948             :               HeapTuple tup, TupleDesc tupdesc)
    5949             : {
    5950             :     /*
    5951             :      * Record is simple - just copy the tuple and its descriptor into the
    5952             :      * record variable
    5953             :      */
    5954        4072 :     if (rec != NULL)
    5955             :     {
    5956             :         /*
    5957             :          * Copy input first, just in case it is pointing at variable's value
    5958             :          */
    5959         927 :         if (HeapTupleIsValid(tup))
    5960         916 :             tup = heap_copytuple(tup);
    5961          11 :         else if (tupdesc)
    5962             :         {
    5963             :             /* If we have a tupdesc but no data, form an all-nulls tuple */
    5964             :             bool       *nulls;
    5965             : 
    5966          11 :             nulls = (bool *)
    5967          11 :                 eval_mcontext_alloc(estate, tupdesc->natts * sizeof(bool));
    5968          11 :             memset(nulls, true, tupdesc->natts * sizeof(bool));
    5969             : 
    5970          11 :             tup = heap_form_tuple(tupdesc, NULL, nulls);
    5971             :         }
    5972             : 
    5973         927 :         if (tupdesc)
    5974         927 :             tupdesc = CreateTupleDescCopy(tupdesc);
    5975             : 
    5976             :         /* Free the old value ... */
    5977         927 :         if (rec->freetup)
    5978             :         {
    5979         435 :             heap_freetuple(rec->tup);
    5980         435 :             rec->freetup = false;
    5981             :         }
    5982         927 :         if (rec->freetupdesc)
    5983             :         {
    5984         435 :             FreeTupleDesc(rec->tupdesc);
    5985         435 :             rec->freetupdesc = false;
    5986             :         }
    5987             : 
    5988             :         /* ... and install the new */
    5989         927 :         if (HeapTupleIsValid(tup))
    5990             :         {
    5991         927 :             rec->tup = tup;
    5992         927 :             rec->freetup = true;
    5993             :         }
    5994             :         else
    5995           0 :             rec->tup = NULL;
    5996             : 
    5997         927 :         if (tupdesc)
    5998             :         {
    5999         927 :             rec->tupdesc = tupdesc;
    6000         927 :             rec->freetupdesc = true;
    6001             :         }
    6002             :         else
    6003           0 :             rec->tupdesc = NULL;
    6004             : 
    6005         927 :         return;
    6006             :     }
    6007             : 
    6008             :     /*
    6009             :      * Row is a bit more complicated in that we assign the individual
    6010             :      * attributes of the tuple to the variables the row points to.
    6011             :      *
    6012             :      * NOTE: this code used to demand row->nfields ==
    6013             :      * HeapTupleHeaderGetNatts(tup->t_data), but that's wrong.  The tuple
    6014             :      * might have more fields than we expected if it's from an
    6015             :      * inheritance-child table of the current table, or it might have fewer if
    6016             :      * the table has had columns added by ALTER TABLE. Ignore extra columns
    6017             :      * and assume NULL for missing columns, the same as heap_getattr would do.
    6018             :      * We also have to skip over dropped columns in either the source or
    6019             :      * destination.
    6020             :      *
    6021             :      * If we have no tuple data at all, we'll assign NULL to all columns of
    6022             :      * the row variable.
    6023             :      */
    6024        3145 :     if (row != NULL)
    6025             :     {
    6026        3145 :         int         td_natts = tupdesc ? tupdesc->natts : 0;
    6027             :         int         t_natts;
    6028             :         int         fnum;
    6029             :         int         anum;
    6030             : 
    6031        3145 :         if (HeapTupleIsValid(tup))
    6032        3126 :             t_natts = HeapTupleHeaderGetNatts(tup->t_data);
    6033             :         else
    6034          19 :             t_natts = 0;
    6035             : 
    6036        3145 :         anum = 0;
    6037        6476 :         for (fnum = 0; fnum < row->nfields; fnum++)
    6038             :         {
    6039             :             PLpgSQL_var *var;
    6040             :             Datum       value;
    6041             :             bool        isnull;
    6042             :             Oid         valtype;
    6043             :             int32       valtypmod;
    6044             : 
    6045        3331 :             if (row->varnos[fnum] < 0)
    6046           0 :                 continue;       /* skip dropped column in row struct */
    6047             : 
    6048        3331 :             var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
    6049             : 
    6050        9975 :             while (anum < td_natts &&
    6051        3313 :                    TupleDescAttr(tupdesc, anum)->attisdropped)
    6052           0 :                 anum++;         /* skip dropped column in tuple */
    6053             : 
    6054        3331 :             if (anum < td_natts)
    6055             :             {
    6056        3313 :                 if (anum < t_natts)
    6057        3302 :                     value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
    6058             :                 else
    6059             :                 {
    6060          11 :                     value = (Datum) 0;
    6061          11 :                     isnull = true;
    6062             :                 }
    6063        3313 :                 valtype = TupleDescAttr(tupdesc, anum)->atttypid;
    6064        3313 :                 valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod;
    6065        3313 :                 anum++;
    6066             :             }
    6067             :             else
    6068             :             {
    6069          18 :                 value = (Datum) 0;
    6070          18 :                 isnull = true;
    6071          18 :                 valtype = UNKNOWNOID;
    6072          18 :                 valtypmod = -1;
    6073             :             }
    6074             : 
    6075        3331 :             exec_assign_value(estate, (PLpgSQL_datum *) var,
    6076             :                               value, isnull, valtype, valtypmod);
    6077             :         }
    6078             : 
    6079        3145 :         return;
    6080             :     }
    6081             : 
    6082           0 :     elog(ERROR, "unsupported target");
    6083             : }
    6084             : 
    6085             : /* ----------
    6086             :  * make_tuple_from_row      Make a tuple from the values of a row object
    6087             :  *
    6088             :  * A NULL return indicates rowtype mismatch; caller must raise suitable error
    6089             :  *
    6090             :  * The result tuple is freshly palloc'd in caller's context.  Some junk
    6091             :  * may be left behind in eval_mcontext, too.
    6092             :  * ----------
    6093             :  */
    6094             : static HeapTuple
    6095          95 : make_tuple_from_row(PLpgSQL_execstate *estate,
    6096             :                     PLpgSQL_row *row,
    6097             :                     TupleDesc tupdesc)
    6098             : {
    6099          95 :     int         natts = tupdesc->natts;
    6100             :     HeapTuple   tuple;
    6101             :     Datum      *dvalues;
    6102             :     bool       *nulls;
    6103             :     int         i;
    6104             : 
    6105          95 :     if (natts != row->nfields)
    6106           0 :         return NULL;
    6107             : 
    6108          95 :     dvalues = (Datum *) eval_mcontext_alloc0(estate, natts * sizeof(Datum));
    6109          95 :     nulls = (bool *) eval_mcontext_alloc(estate, natts * sizeof(bool));
    6110             : 
    6111         280 :     for (i = 0; i < natts; i++)
    6112             :     {
    6113             :         Oid         fieldtypeid;
    6114             :         int32       fieldtypmod;
    6115             : 
    6116         185 :         if (TupleDescAttr(tupdesc, i)->attisdropped)
    6117             :         {
    6118           0 :             nulls[i] = true;    /* leave the column as null */
    6119           0 :             continue;
    6120             :         }
    6121         185 :         if (row->varnos[i] < 0) /* should not happen */
    6122           0 :             elog(ERROR, "dropped rowtype entry for non-dropped column");
    6123             : 
    6124         370 :         exec_eval_datum(estate, estate->datums[row->varnos[i]],
    6125             :                         &fieldtypeid, &fieldtypmod,
    6126         185 :                         &dvalues[i], &nulls[i]);
    6127         185 :         if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid)
    6128           0 :             return NULL;
    6129             :         /* XXX should we insist on typmod match, too? */
    6130             :     }
    6131             : 
    6132          95 :     tuple = heap_form_tuple(tupdesc, dvalues, nulls);
    6133             : 
    6134          95 :     return tuple;
    6135             : }
    6136             : 
    6137             : /* ----------
    6138             :  * get_tuple_from_datum     extract a tuple from a composite Datum
    6139             :  *
    6140             :  * Returns a HeapTuple, freshly palloc'd in caller's context.
    6141             :  *
    6142             :  * Note: it's caller's responsibility to be sure value is of composite type.
    6143             :  * ----------
    6144             :  */
    6145             : static HeapTuple
    6146          88 : get_tuple_from_datum(Datum value)
    6147             : {
    6148          88 :     HeapTupleHeader td = DatumGetHeapTupleHeader(value);
    6149             :     HeapTupleData tmptup;
    6150             : 
    6151             :     /* Build a temporary HeapTuple control structure */
    6152          88 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
    6153          88 :     ItemPointerSetInvalid(&(tmptup.t_self));
    6154          88 :     tmptup.t_tableOid = InvalidOid;
    6155          88 :     tmptup.t_data = td;
    6156             : 
    6157             :     /* Build a copy and return it */
    6158          88 :     return heap_copytuple(&tmptup);
    6159             : }
    6160             : 
    6161             : /* ----------
    6162             :  * get_tupdesc_from_datum   get a tuple descriptor for a composite Datum
    6163             :  *
    6164             :  * Returns a pointer to the TupleDesc of the tuple's rowtype.
    6165             :  * Caller is responsible for calling ReleaseTupleDesc when done with it.
    6166             :  *
    6167             :  * Note: it's caller's responsibility to be sure value is of composite type.
    6168             :  * ----------
    6169             :  */
    6170             : static TupleDesc
    6171          88 : get_tupdesc_from_datum(Datum value)
    6172             : {
    6173          88 :     HeapTupleHeader td = DatumGetHeapTupleHeader(value);
    6174             :     Oid         tupType;
    6175             :     int32       tupTypmod;
    6176             : 
    6177             :     /* Extract rowtype info and find a tupdesc */
    6178          88 :     tupType = HeapTupleHeaderGetTypeId(td);
    6179          88 :     tupTypmod = HeapTupleHeaderGetTypMod(td);
    6180          88 :     return lookup_rowtype_tupdesc(tupType, tupTypmod);
    6181             : }
    6182             : 
    6183             : /* ----------
    6184             :  * exec_move_row_from_datum     Move a composite Datum into a record or row
    6185             :  *
    6186             :  * This is equivalent to get_tuple_from_datum() followed by exec_move_row(),
    6187             :  * but we avoid constructing an intermediate physical copy of the tuple.
    6188             :  * ----------
    6189             :  */
    6190             : static void
    6191          69 : exec_move_row_from_datum(PLpgSQL_execstate *estate,
    6192             :                          PLpgSQL_rec *rec,
    6193             :                          PLpgSQL_row *row,
    6194             :                          Datum value)
    6195             : {
    6196          69 :     HeapTupleHeader td = DatumGetHeapTupleHeader(value);
    6197             :     Oid         tupType;
    6198             :     int32       tupTypmod;
    6199             :     TupleDesc   tupdesc;
    6200             :     HeapTupleData tmptup;
    6201             : 
    6202             :     /* Extract rowtype info and find a tupdesc */
    6203          69 :     tupType = HeapTupleHeaderGetTypeId(td);
    6204          69 :     tupTypmod = HeapTupleHeaderGetTypMod(td);
    6205          69 :     tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    6206             : 
    6207             :     /* Build a temporary HeapTuple control structure */
    6208          69 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
    6209          69 :     ItemPointerSetInvalid(&(tmptup.t_self));
    6210          69 :     tmptup.t_tableOid = InvalidOid;
    6211          69 :     tmptup.t_data = td;
    6212             : 
    6213             :     /* Do the move */
    6214          69 :     exec_move_row(estate, rec, row, &tmptup, tupdesc);
    6215             : 
    6216             :     /* Release tupdesc usage count */
    6217          69 :     ReleaseTupleDesc(tupdesc);
    6218          69 : }
    6219             : 
    6220             : /* ----------
    6221             :  * convert_value_to_string          Convert a non-null Datum to C string
    6222             :  *
    6223             :  * Note: the result is in the estate's eval_mcontext, and will be cleared
    6224             :  * by the next exec_eval_cleanup() call.  The invoked output function might
    6225             :  * leave additional cruft there as well, so just pfree'ing the result string
    6226             :  * would not be enough to avoid memory leaks if we did not do it like this.
    6227             :  * In most usages the Datum being passed in is also in that context (if
    6228             :  * pass-by-reference) and so an exec_eval_cleanup() call is needed anyway.
    6229             :  *
    6230             :  * Note: not caching the conversion function lookup is bad for performance.
    6231             :  * However, this function isn't currently used in any places where an extra
    6232             :  * catalog lookup or two seems like a big deal.
    6233             :  * ----------
    6234             :  */
    6235             : static char *
    6236        3675 : convert_value_to_string(PLpgSQL_execstate *estate, Datum value, Oid valtype)
    6237             : {
    6238             :     char       *result;
    6239             :     MemoryContext oldcontext;
    6240             :     Oid         typoutput;
    6241             :     bool        typIsVarlena;
    6242             : 
    6243        3675 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    6244        3675 :     getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
    6245        3675 :     result = OidOutputFunctionCall(typoutput, value);
    6246        3675 :     MemoryContextSwitchTo(oldcontext);
    6247             : 
    6248        3675 :     return result;
    6249             : }
    6250             : 
    6251             : /* ----------
    6252             :  * exec_cast_value          Cast a value if required
    6253             :  *
    6254             :  * Note that *isnull is an input and also an output parameter.  While it's
    6255             :  * unlikely that a cast operation would produce null from non-null or vice
    6256             :  * versa, that could happen in principle.
    6257             :  *
    6258             :  * Note: the estate's eval_mcontext is used for temporary storage, and may
    6259             :  * also contain the result Datum if we have to do a conversion to a pass-
    6260             :  * by-reference data type.  Be sure to do an exec_eval_cleanup() call when
    6261             :  * done with the result.
    6262             :  * ----------
    6263             :  */
    6264             : static Datum
    6265       31432 : exec_cast_value(PLpgSQL_execstate *estate,
    6266             :                 Datum value, bool *isnull,
    6267             :                 Oid valtype, int32 valtypmod,
    6268             :                 Oid reqtype, int32 reqtypmod)
    6269             : {
    6270             :     /*
    6271             :      * If the type of the given value isn't what's requested, convert it.
    6272             :      */
    6273       31432 :     if (valtype != reqtype ||
    6274           6 :         (valtypmod != reqtypmod && reqtypmod != -1))
    6275             :     {
    6276             :         plpgsql_CastHashEntry *cast_entry;
    6277             : 
    6278         886 :         cast_entry = get_cast_hashentry(estate,
    6279             :                                         valtype, valtypmod,
    6280             :                                         reqtype, reqtypmod);
    6281         886 :         if (cast_entry)
    6282             :         {
    6283         869 :             ExprContext *econtext = estate->eval_econtext;
    6284             :             MemoryContext oldcontext;
    6285             : 
    6286         869 :             oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    6287             : 
    6288         869 :             econtext->caseValue_datum = value;
    6289         869 :             econtext->caseValue_isNull = *isnull;
    6290             : 
    6291         869 :             cast_entry->cast_in_use = true;
    6292             : 
    6293         869 :             value = ExecEvalExpr(cast_entry->cast_exprstate, econtext,
    6294             :                                  isnull);
    6295             : 
    6296         851 :             cast_entry->cast_in_use = false;
    6297             : 
    6298         851 :             MemoryContextSwitchTo(oldcontext);
    6299             :         }
    6300             :     }
    6301             : 
    6302       31414 :     return value;
    6303             : }
    6304             : 
    6305             : /* ----------
    6306             :  * get_cast_hashentry           Look up how to perform a type cast
    6307             :  *
    6308             :  * Returns a plpgsql_CastHashEntry if an expression has to be evaluated,
    6309             :  * or NULL if the cast is a mere no-op relabeling.  If there's work to be
    6310             :  * done, the cast_exprstate field contains an expression evaluation tree
    6311             :  * based on a CaseTestExpr input, and the cast_in_use field should be set
    6312             :  * TRUE while executing it.
    6313             :  * ----------
    6314             :  */
    6315             : static plpgsql_CastHashEntry *
    6316         886 : get_cast_hashentry(PLpgSQL_execstate *estate,
    6317             :                    Oid srctype, int32 srctypmod,
    6318             :                    Oid dsttype, int32 dsttypmod)
    6319             : {
    6320             :     plpgsql_CastHashKey cast_key;
    6321             :     plpgsql_CastHashEntry *cast_entry;
    6322             :     bool        found;
    6323             :     LocalTransactionId curlxid;
    6324             :     MemoryContext oldcontext;
    6325             : 
    6326             :     /* Look for existing entry */
    6327         886 :     cast_key.srctype = srctype;
    6328         886 :     cast_key.dsttype = dsttype;
    6329         886 :     cast_key.srctypmod = srctypmod;
    6330         886 :     cast_key.dsttypmod = dsttypmod;
    6331         886 :     cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
    6332             :                                                        (void *) &cast_key,
    6333             :                                                        HASH_FIND, NULL);
    6334             : 
    6335         886 :     if (cast_entry == NULL)
    6336             :     {
    6337             :         /* We've not looked up this coercion before */
    6338             :         Node       *cast_expr;
    6339             :         CaseTestExpr *placeholder;
    6340             : 
    6341             :         /*
    6342             :          * Since we could easily fail (no such coercion), construct a
    6343             :          * temporary coercion expression tree in the short-lived
    6344             :          * eval_mcontext, then if successful copy it to cast_hash_context.
    6345             :          */
    6346          46 :         oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    6347             : 
    6348             :         /*
    6349             :          * We use a CaseTestExpr as the base of the coercion tree, since it's
    6350             :          * very cheap to insert the source value for that.
    6351             :          */
    6352          46 :         placeholder = makeNode(CaseTestExpr);
    6353          46 :         placeholder->typeId = srctype;
    6354          46 :         placeholder->typeMod = srctypmod;
    6355          46 :         placeholder->collation = get_typcollation(srctype);
    6356             : 
    6357             :         /*
    6358             :          * Apply coercion.  We use ASSIGNMENT coercion because that's the
    6359             :          * closest match to plpgsql's historical behavior; in particular,
    6360             :          * EXPLICIT coercion would allow silent truncation to a destination
    6361             :          * varchar/bpchar's length, which we do not want.
    6362             :          *
    6363             :          * If source type is UNKNOWN, coerce_to_target_type will fail (it only
    6364             :          * expects to see that for Const input nodes), so don't call it; we'll
    6365             :          * apply CoerceViaIO instead.  Likewise, it doesn't currently work for
    6366             :          * coercing RECORD to some other type, so skip for that too.
    6367             :          */
    6368          46 :         if (srctype == UNKNOWNOID || srctype == RECORDOID)
    6369          10 :             cast_expr = NULL;
    6370             :         else
    6371          36 :             cast_expr = coerce_to_target_type(NULL,
    6372             :                                               (Node *) placeholder, srctype,
    6373             :                                               dsttype, dsttypmod,
    6374             :                                               COERCION_ASSIGNMENT,
    6375             :                                               COERCE_IMPLICIT_CAST,
    6376             :                                               -1);
    6377             : 
    6378             :         /*
    6379             :          * If there's no cast path according to the parser, fall back to using
    6380             :          * an I/O coercion; this is semantically dubious but matches plpgsql's
    6381             :          * historical behavior.  We would need something of the sort for
    6382             :          * UNKNOWN literals in any case.
    6383             :          */
    6384          46 :         if (cast_expr == NULL)
    6385             :         {
    6386          17 :             CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
    6387             : 
    6388          17 :             iocoerce->arg = (Expr *) placeholder;
    6389          17 :             iocoerce->resulttype = dsttype;
    6390          17 :             iocoerce->resultcollid = InvalidOid;
    6391          17 :             iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
    6392          17 :             iocoerce->location = -1;
    6393          17 :             cast_expr = (Node *) iocoerce;
    6394          17 :             if (dsttypmod != -1)
    6395           0 :                 cast_expr = coerce_to_target_type(NULL,
    6396             :                                                   cast_expr, dsttype,
    6397             :                                                   dsttype, dsttypmod,
    6398             :                                                   COERCION_ASSIGNMENT,
    6399             :                                                   COERCE_IMPLICIT_CAST,
    6400             :                                                   -1);
    6401             :         }
    6402             : 
    6403             :         /* Note: we don't bother labeling the expression tree with collation */
    6404             : 
    6405             :         /* Detect whether we have a no-op (RelabelType) coercion */
    6406          47 :         if (IsA(cast_expr, RelabelType) &&
    6407           1 :             ((RelabelType *) cast_expr)->arg == (Expr *) placeholder)
    6408           1 :             cast_expr = NULL;
    6409             : 
    6410          46 :         if (cast_expr)
    6411             :         {
    6412             :             /* ExecInitExpr assumes we've planned the expression */
    6413          45 :             cast_expr = (Node *) expression_planner((Expr *) cast_expr);
    6414             : 
    6415             :             /* Now copy the tree into cast_hash_context */
    6416          45 :             MemoryContextSwitchTo(estate->cast_hash_context);
    6417             : 
    6418          45 :             cast_expr = copyObject(cast_expr);
    6419             :         }
    6420             : 
    6421          46 :         MemoryContextSwitchTo(oldcontext);
    6422             : 
    6423             :         /* Now we can fill in a hashtable entry. */
    6424          46 :         cast_entry = (plpgsql_CastHashEntry *) hash_search(estate->cast_hash,
    6425             :                                                            (void *) &cast_key,
    6426             :                                                            HASH_ENTER, &found);
    6427          46 :         Assert(!found);         /* wasn't there a moment ago */
    6428          46 :         cast_entry->cast_expr = (Expr *) cast_expr;
    6429          46 :         cast_entry->cast_exprstate = NULL;
    6430          46 :         cast_entry->cast_in_use = false;
    6431          46 :         cast_entry->cast_lxid = InvalidLocalTransactionId;
    6432             :     }
    6433             : 
    6434             :     /* Done if we have determined that this is a no-op cast. */
    6435         886 :     if (cast_entry->cast_expr == NULL)
    6436          17 :         return NULL;
    6437             : 
    6438             :     /*
    6439             :      * Prepare the expression for execution, if it's not been done already in
    6440             :      * the current transaction; also, if it's marked busy in the current
    6441             :      * transaction, abandon that expression tree and build a new one, so as to
    6442             :      * avoid potential problems with recursive cast expressions and failed
    6443             :      * executions.  (We will leak some memory intra-transaction if that
    6444             :      * happens a lot, but we don't expect it to.)  It's okay to update the
    6445             :      * hash table with the new tree because all plpgsql functions within a
    6446             :      * given transaction share the same simple_eval_estate.  (Well, regular
    6447             :      * functions do; DO blocks have private simple_eval_estates, and private
    6448             :      * cast hash tables to go with them.)
    6449             :      */
    6450         869 :     curlxid = MyProc->lxid;
    6451         869 :     if (cast_entry->cast_lxid != curlxid || cast_entry->cast_in_use)
    6452             :     {
    6453         246 :         oldcontext = MemoryContextSwitchTo(estate->simple_eval_estate->es_query_cxt);
    6454         246 :         cast_entry->cast_exprstate = ExecInitExpr(cast_entry->cast_expr, NULL);
    6455         246 :         cast_entry->cast_in_use = false;
    6456         246 :         cast_entry->cast_lxid = curlxid;
    6457         246 :         MemoryContextSwitchTo(oldcontext);
    6458             :     }
    6459             : 
    6460         869 :     return cast_entry;
    6461             : }
    6462             : 
    6463             : 
    6464             : /* ----------
    6465             :  * exec_simple_check_plan -     Check if a plan is simple enough to
    6466             :  *                              be evaluated by ExecEvalExpr() instead
    6467             :  *                              of SPI.
    6468             :  * ----------
    6469             :  */
    6470             : static void
    6471        1584 : exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
    6472             : {
    6473             :     List       *plansources;
    6474             :     CachedPlanSource *plansource;
    6475             :     Query      *query;
    6476             :     CachedPlan *cplan;
    6477             :     MemoryContext oldcontext;
    6478             : 
    6479             :     /*
    6480             :      * Initialize to "not simple".
    6481             :      */
    6482        1584 :     expr->expr_simple_expr = NULL;
    6483             : 
    6484             :     /*
    6485             :      * Check the analyzed-and-rewritten form of the query to see if we will be
    6486             :      * able to treat it as a simple expression.  Since this function is only
    6487             :      * called immediately after creating the CachedPlanSource, we need not
    6488             :      * worry about the query being stale.
    6489             :      */
    6490             : 
    6491             :     /*
    6492             :      * We can only test queries that resulted in exactly one CachedPlanSource
    6493             :      */
    6494        1584 :     plansources = SPI_plan_get_plan_sources(expr->plan);
    6495        1584 :     if (list_length(plansources) != 1)
    6496           0 :         return;
    6497        1584 :     plansource = (CachedPlanSource *) linitial(plansources);
    6498             : 
    6499             :     /*
    6500             :      * 1. There must be one single querytree.
    6501             :      */
    6502        1584 :     if (list_length(plansource->query_list) != 1)
    6503           0 :         return;
    6504        1584 :     query = (Query *) linitial(plansource->query_list);
    6505             : 
    6506             :     /*
    6507             :      * 2. It must be a plain SELECT query without any input tables
    6508             :      */
    6509        1584 :     if (!IsA(query, Query))
    6510           0 :         return;
    6511        1584 :     if (query->commandType != CMD_SELECT)
    6512          87 :         return;
    6513        1497 :     if (query->rtable != NIL)
    6514         102 :         return;
    6515             : 
    6516             :     /*
    6517             :      * 3. Can't have any subplans, aggregates, qual clauses either.  (These
    6518             :      * tests should generally match what inline_function() checks before
    6519             :      * inlining a SQL function; otherwise, inlining could change our
    6520             :      * conclusion about whether an expression is simple, which we don't want.)
    6521             :      */
    6522        2790 :     if (query->hasAggs ||
    6523        2790 :         query->hasWindowFuncs ||
    6524        2790 :         query->hasTargetSRFs ||
    6525        2750 :         query->hasSubLinks ||
    6526        2710 :         query->cteList ||
    6527        2710 :         query->jointree->fromlist ||
    6528        2710 :         query->jointree->quals ||
    6529        2710 :         query->groupClause ||
    6530        2710 :         query->groupingSets ||
    6531        2710 :         query->havingQual ||
    6532        2710 :         query->windowClause ||
    6533        2710 :         query->distinctClause ||
    6534        2710 :         query->sortClause ||
    6535        2710 :         query->limitOffset ||
    6536        2710 :         query->limitCount ||
    6537        1355 :         query->setOperations)
    6538          40 :         return;
    6539             : 
    6540             :     /*
    6541             :      * 4. The query must have a single attribute as result
    6542             :      */
    6543        1355 :     if (list_length(query->targetList) != 1)
    6544          12 :         return;
    6545             : 
    6546             :     /*
    6547             :      * OK, we can treat it as a simple plan.
    6548             :      *
    6549             :      * Get the generic plan for the query.  If replanning is needed, do that
    6550             :      * work in the eval_mcontext.
    6551             :      */
    6552        1343 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    6553        1343 :     cplan = SPI_plan_get_cached_plan(expr->plan);
    6554        1338 :     MemoryContextSwitchTo(oldcontext);
    6555             : 
    6556             :     /* Can't fail, because we checked for a single CachedPlanSource above */
    6557        1338 :     Assert(cplan != NULL);
    6558             : 
    6559             :     /* Share the remaining work with replan code path */
    6560        1338 :     exec_save_simple_expr(expr, cplan);
    6561             : 
    6562             :     /* Release our plan refcount */
    6563        1338 :     ReleaseCachedPlan(cplan, true);
    6564             : }
    6565             : 
    6566             : /*
    6567             :  * exec_save_simple_expr --- extract simple expression from CachedPlan
    6568             :  */
    6569             : static void
    6570        1847 : exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
    6571             : {
    6572             :     PlannedStmt *stmt;
    6573             :     Plan       *plan;
    6574             :     Expr       *tle_expr;
    6575             : 
    6576             :     /*
    6577             :      * Given the checks that exec_simple_check_plan did, none of the Asserts
    6578             :      * here should ever fail.
    6579             :      */
    6580             : 
    6581             :     /* Extract the single PlannedStmt */
    6582        1847 :     Assert(list_length(cplan->stmt_list) == 1);
    6583        1847 :     stmt = linitial_node(PlannedStmt, cplan->stmt_list);
    6584        1847 :     Assert(stmt->commandType == CMD_SELECT);
    6585             : 
    6586             :     /*
    6587             :      * Ordinarily, the plan node should be a simple Result.  However, if
    6588             :      * force_parallel_mode is on, the planner might've stuck a Gather node
    6589             :      * atop that.  The simplest way to deal with this is to look through the
    6590             :      * Gather node.  The Gather node's tlist would normally contain a Var
    6591             :      * referencing the child node's output ... but setrefs.c might also have
    6592             :      * copied a Const as-is.
    6593             :      */
    6594        1847 :     plan = stmt->planTree;
    6595             :     for (;;)
    6596             :     {
    6597             :         /* Extract the single tlist expression */
    6598        1847 :         Assert(list_length(plan->targetlist) == 1);
    6599        1847 :         tle_expr = castNode(TargetEntry, linitial(plan->targetlist))->expr;
    6600             : 
    6601        1847 :         if (IsA(plan, Result))
    6602             :         {
    6603        1847 :             Assert(plan->lefttree == NULL &&
    6604             :                    plan->righttree == NULL &&
    6605             :                    plan->initPlan == NULL &&
    6606             :                    plan->qual == NULL &&
    6607             :                    ((Result *) plan)->resconstantqual == NULL);
    6608        1847 :             break;
    6609             :         }
    6610           0 :         else if (IsA(plan, Gather))
    6611             :         {
    6612           0 :             Assert(plan->lefttree != NULL &&
    6613             :                    plan->righttree == NULL &&
    6614             :                    plan->initPlan == NULL &&
    6615             :                    plan->qual == NULL);
    6616             :             /* If setrefs.c copied up a Const, no need to look further */
    6617           0 :             if (IsA(tle_expr, Const))
    6618           0 :                 break;
    6619             :             /* Otherwise, it better be an outer Var */
    6620           0 :             Assert(IsA(tle_expr, Var));
    6621           0 :             Assert(((Var *) tle_expr)->varno == OUTER_VAR);
    6622             :             /* Descend to the child node */
    6623           0 :             plan = plan->lefttree;
    6624             :         }
    6625             :         else
    6626           0 :             elog(ERROR, "unexpected plan node type: %d",
    6627             :                  (int) nodeTag(plan));
    6628           0 :     }
    6629             : 
    6630             :     /*
    6631             :      * Save the simple expression, and initialize state to "not valid in
    6632             :      * current transaction".
    6633             :      */
    6634        1847 :     expr->expr_simple_expr = tle_expr;
    6635        1847 :     expr->expr_simple_generation = cplan->generation;
    6636        1847 :     expr->expr_simple_state = NULL;
    6637        1847 :     expr->expr_simple_in_use = false;
    6638        1847 :     expr->expr_simple_lxid = InvalidLocalTransactionId;
    6639             :     /* Also stash away the expression result type */
    6640        1847 :     expr->expr_simple_type = exprType((Node *) tle_expr);
    6641        1847 :     expr->expr_simple_typmod = exprTypmod((Node *) tle_expr);
    6642        1847 : }
    6643             : 
    6644             : /*
    6645             :  * exec_check_rw_parameter --- can we pass expanded object as read/write param?
    6646             :  *
    6647             :  * If we have an assignment like "x := array_append(x, foo)" in which the
    6648             :  * top-level function is trusted not to corrupt its argument in case of an
    6649             :  * error, then when x has an expanded object as value, it is safe to pass the
    6650             :  * value as a read/write pointer and let the function modify the value
    6651             :  * in-place.
    6652             :  *
    6653             :  * This function checks for a safe expression, and sets expr->rwparam to the
    6654             :  * dno of the target variable (x) if safe, or -1 if not safe.
    6655             :  */
    6656             : static void
    6657         246 : exec_check_rw_parameter(PLpgSQL_expr *expr, int target_dno)
    6658             : {
    6659             :     Oid         funcid;
    6660             :     List       *fargs;
    6661             :     ListCell   *lc;
    6662             : 
    6663             :     /* Assume unsafe */
    6664         246 :     expr->rwparam = -1;
    6665             : 
    6666             :     /*
    6667             :      * If the expression isn't simple, there's no point in trying to optimize
    6668             :      * (because the exec_run_select code path will flatten any expanded result
    6669             :      * anyway).  Even without that, this seems like a good safety restriction.
    6670             :      */
    6671         246 :     if (expr->expr_simple_expr == NULL)
    6672           7 :         return;
    6673             : 
    6674             :     /*
    6675             :      * If target variable isn't referenced by expression, no need to look
    6676             :      * further.
    6677             :      */
    6678         239 :     if (!bms_is_member(target_dno, expr->paramnos))
    6679         177 :         return;
    6680             : 
    6681             :     /*
    6682             :      * Top level of expression must be a simple FuncExpr or OpExpr.
    6683             :      */
    6684          62 :     if (IsA(expr->expr_simple_expr, FuncExpr))
    6685             :     {
    6686           3 :         FuncExpr   *fexpr = (FuncExpr *) expr->expr_simple_expr;
    6687             : 
    6688           3 :         funcid = fexpr->funcid;
    6689           3 :         fargs = fexpr->args;
    6690             :     }
    6691          59 :     else if (IsA(expr->expr_simple_expr, OpExpr))
    6692             :     {
    6693          59 :         OpExpr     *opexpr = (OpExpr *) expr->expr_simple_expr;
    6694             : 
    6695          59 :         funcid = opexpr->opfuncid;
    6696          59 :         fargs = opexpr->args;
    6697             :     }
    6698             :     else
    6699           0 :         return;
    6700             : 
    6701             :     /*
    6702             :      * The top-level function must be one that we trust to be "safe".
    6703             :      * Currently we hard-wire the list, but it would be very desirable to
    6704             :      * allow extensions to mark their functions as safe ...
    6705             :      */
    6706          62 :     if (!(funcid == F_ARRAY_APPEND ||
    6707             :           funcid == F_ARRAY_PREPEND))
    6708          60 :         return;
    6709             : 
    6710             :     /*
    6711             :      * The target variable (in the form of a Param) must only appear as a
    6712             :      * direct argument of the top-level function.
    6713             :      */
    6714           3 :     foreach(lc, fargs)
    6715             :     {
    6716           3 :         Node       *arg = (Node *) lfirst(lc);
    6717             : 
    6718             :         /* A Param is OK, whether it's the target variable or not */
    6719           3 :         if (arg && IsA(arg, Param))
    6720           0 :             continue;
    6721             :         /* Otherwise, argument expression must not reference target */
    6722           3 :         if (contains_target_param(arg, &target_dno))
    6723           2 :             return;
    6724             :     }
    6725             : 
    6726             :     /* OK, we can pass target as a read-write parameter */
    6727           0 :     expr->rwparam = target_dno;
    6728             : }
    6729             : 
    6730             : /*
    6731             :  * Recursively check for a Param referencing the target variable
    6732             :  */
    6733             : static bool
    6734           5 : contains_target_param(Node *node, int *target_dno)
    6735             : {
    6736           5 :     if (node == NULL)
    6737           0 :         return false;
    6738           5 :     if (IsA(node, Param))
    6739             :     {
    6740           2 :         Param      *param = (Param *) node;
    6741             : 
    6742           4 :         if (param->paramkind == PARAM_EXTERN &&
    6743           2 :             param->paramid == *target_dno + 1)
    6744           2 :             return true;
    6745           0 :         return false;
    6746             :     }
    6747           3 :     return expression_tree_walker(node, contains_target_param,
    6748             :                                   (void *) target_dno);
    6749             : }
    6750             : 
    6751             : /* ----------
    6752             :  * exec_set_found           Set the global found variable to true/false
    6753             :  * ----------
    6754             :  */
    6755             : static void
    6756       14046 : exec_set_found(PLpgSQL_execstate *estate, bool state)
    6757             : {
    6758             :     PLpgSQL_var *var;
    6759             : 
    6760       14046 :     var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
    6761       14046 :     assign_simple_var(estate, var, BoolGetDatum(state), false, false);
    6762       14046 : }
    6763             : 
    6764             : /*
    6765             :  * plpgsql_create_econtext --- create an eval_econtext for the current function
    6766             :  *
    6767             :  * We may need to create a new shared_simple_eval_estate too, if there's not
    6768             :  * one already for the current transaction.  The EState will be cleaned up at
    6769             :  * transaction end.
    6770             :  */
    6771             : static void
    6772       12578 : plpgsql_create_econtext(PLpgSQL_execstate *estate)
    6773             : {
    6774             :     SimpleEcontextStackEntry *entry;
    6775             : 
    6776             :     /*
    6777             :      * Create an EState for evaluation of simple expressions, if there's not
    6778             :      * one already in the current transaction.  The EState is made a child of
    6779             :      * TopTransactionContext so it will have the right lifespan.
    6780             :      *
    6781             :      * Note that this path is never taken when executing a DO block; the
    6782             :      * required EState was already made by plpgsql_inline_handler.
    6783             :      */
    6784       12578 :     if (estate->simple_eval_estate == NULL)
    6785             :     {
    6786             :         MemoryContext oldcontext;
    6787             : 
    6788         767 :         Assert(shared_simple_eval_estate == NULL);
    6789         767 :         oldcontext = MemoryContextSwitchTo(TopTransactionContext);
    6790         767 :         shared_simple_eval_estate = CreateExecutorState();
    6791         767 :         estate->simple_eval_estate = shared_simple_eval_estate;
    6792         767 :         MemoryContextSwitchTo(oldcontext);
    6793             :     }
    6794             : 
    6795             :     /*
    6796             :      * Create a child econtext for the current function.
    6797             :      */
    6798       12578 :     estate->eval_econtext = CreateExprContext(estate->simple_eval_estate);
    6799             : 
    6800             :     /*
    6801             :      * Make a stack entry so we can clean up the econtext at subxact end.
    6802             :      * Stack entries are kept in TopTransactionContext for simplicity.
    6803             :      */
    6804       12578 :     entry = (SimpleEcontextStackEntry *)
    6805       12578 :         MemoryContextAlloc(TopTransactionContext,
    6806             :                            sizeof(SimpleEcontextStackEntry));
    6807             : 
    6808       12578 :     entry->stack_econtext = estate->eval_econtext;
    6809       12578 :     entry->xact_subxid = GetCurrentSubTransactionId();
    6810             : 
    6811       12578 :     entry->next = simple_econtext_stack;
    6812       12578 :     simple_econtext_stack = entry;
    6813       12578 : }
    6814             : 
    6815             : /*
    6816             :  * plpgsql_destroy_econtext --- destroy function's econtext
    6817             :  *
    6818             :  * We check that it matches the top stack entry, and destroy the stack
    6819             :  * entry along with the context.
    6820             :  */
    6821             : static void
    6822       12208 : plpgsql_destroy_econtext(PLpgSQL_execstate *estate)
    6823             : {
    6824             :     SimpleEcontextStackEntry *next;
    6825             : 
    6826       12208 :     Assert(simple_econtext_stack != NULL);
    6827       12208 :     Assert(simple_econtext_stack->stack_econtext == estate->eval_econtext);
    6828             : 
    6829       12208 :     next = simple_econtext_stack->next;
    6830       12208 :     pfree(simple_econtext_stack);
    6831       12208 :     simple_econtext_stack = next;
    6832             : 
    6833       12208 :     FreeExprContext(estate->eval_econtext, true);
    6834       12208 :     estate->eval_econtext = NULL;
    6835       12208 : }
    6836             : 
    6837             : /*
    6838             :  * plpgsql_xact_cb --- post-transaction-commit-or-abort cleanup
    6839             :  *
    6840             :  * If a simple-expression EState was created in the current transaction,
    6841             :  * it has to be cleaned up.
    6842             :  */
    6843             : void
    6844       13913 : plpgsql_xact_cb(XactEvent event, void *arg)
    6845             : {
    6846             :     /*
    6847             :      * If we are doing a clean transaction shutdown, free the EState (so that
    6848             :      * any remaining resources will be released correctly). In an abort, we
    6849             :      * expect the regular abort recovery procedures to release everything of
    6850             :      * interest.
    6851             :      */
    6852       13913 :     if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE)
    6853             :     {
    6854             :         /* Shouldn't be any econtext stack entries left at commit */
    6855        6411 :         Assert(simple_econtext_stack == NULL);
    6856             : 
    6857        6411 :         if (shared_simple_eval_estate)
    6858         656 :             FreeExecutorState(shared_simple_eval_estate);
    6859        6411 :         shared_simple_eval_estate = NULL;
    6860             :     }
    6861        7502 :     else if (event == XACT_EVENT_ABORT)
    6862             :     {
    6863         862 :         simple_econtext_stack = NULL;
    6864         862 :         shared_simple_eval_estate = NULL;
    6865             :     }
    6866       13913 : }
    6867             : 
    6868             : /*
    6869             :  * plpgsql_subxact_cb --- post-subtransaction-commit-or-abort cleanup
    6870             :  *
    6871             :  * Make sure any simple-expression econtexts created in the current
    6872             :  * subtransaction get cleaned up.  We have to do this explicitly because
    6873             :  * no other code knows which econtexts belong to which level of subxact.
    6874             :  */
    6875             : void
    6876         636 : plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
    6877             :                    SubTransactionId parentSubid, void *arg)
    6878             : {
    6879         636 :     if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
    6880             :     {
    6881        1466 :         while (simple_econtext_stack != NULL &&
    6882         544 :                simple_econtext_stack->xact_subxid == mySubid)
    6883             :         {
    6884             :             SimpleEcontextStackEntry *next;
    6885             : 
    6886         282 :             FreeExprContext(simple_econtext_stack->stack_econtext,
    6887             :                             (event == SUBXACT_EVENT_COMMIT_SUB));
    6888         282 :             next = simple_econtext_stack->next;
    6889         282 :             pfree(simple_econtext_stack);
    6890         282 :             simple_econtext_stack = next;
    6891             :         }
    6892             :     }
    6893         636 : }
    6894             : 
    6895             : /*
    6896             :  * assign_simple_var --- assign a new value to any VAR datum.
    6897             :  *
    6898             :  * This should be the only mechanism for assignment to simple variables,
    6899             :  * lest we forget to update the paramLI image.
    6900             :  */
    6901             : static void
    6902       56280 : assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var,
    6903             :                   Datum newvalue, bool isnull, bool freeable)
    6904             : {
    6905             :     ParamExternData *prm;
    6906             : 
    6907       56280 :     Assert(var->dtype == PLPGSQL_DTYPE_VAR);
    6908             :     /* Free the old value if needed */
    6909       56280 :     if (var->freeval)
    6910             :     {
    6911        3824 :         if (DatumIsReadWriteExpandedObject(var->value,
    6912             :                                            var->isnull,
    6913             :                                            var->datatype->typlen))
    6914         785 :             DeleteExpandedObject(var->value);
    6915             :         else
    6916        3039 :             pfree(DatumGetPointer(var->value));
    6917             :     }
    6918             :     /* Assign new value to datum */
    6919       56280 :     var->value = newvalue;
    6920       56280 :     var->isnull = isnull;
    6921       56280 :     var->freeval = freeable;
    6922             :     /* And update the image in the common parameter list */
    6923       56280 :     prm = &estate->paramLI->params[var->dno];
    6924       56280 :     prm->value = MakeExpandedObjectReadOnly(newvalue,
    6925             :                                             isnull,
    6926             :                                             var->datatype->typlen);
    6927       56280 :     prm->isnull = isnull;
    6928             :     /* these might be set already, but let's be sure */
    6929       56280 :     prm->pflags = PARAM_FLAG_CONST;
    6930       56280 :     prm->ptype = var->datatype->typoid;
    6931       56280 : }
    6932             : 
    6933             : /*
    6934             :  * free old value of a text variable and assign new value from C string
    6935             :  */
    6936             : static void
    6937        6068 : assign_text_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, const char *str)
    6938             : {
    6939        6068 :     assign_simple_var(estate, var, CStringGetTextDatum(str), false, true);
    6940        6068 : }
    6941             : 
    6942             : /*
    6943             :  * exec_eval_using_params --- evaluate params of USING clause
    6944             :  *
    6945             :  * The result data structure is created in the stmt_mcontext, and should
    6946             :  * be freed by resetting that context.
    6947             :  */
    6948             : static PreparedParamsData *
    6949           6 : exec_eval_using_params(PLpgSQL_execstate *estate, List *params)
    6950             : {
    6951             :     PreparedParamsData *ppd;
    6952           6 :     MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
    6953             :     int         nargs;
    6954             :     int         i;
    6955             :     ListCell   *lc;
    6956             : 
    6957           6 :     ppd = (PreparedParamsData *)
    6958             :         MemoryContextAlloc(stmt_mcontext, sizeof(PreparedParamsData));
    6959           6 :     nargs = list_length(params);
    6960             : 
    6961           6 :     ppd->nargs = nargs;
    6962           6 :     ppd->types = (Oid *)
    6963           6 :         MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Oid));
    6964           6 :     ppd->values = (Datum *)
    6965           6 :         MemoryContextAlloc(stmt_mcontext, nargs * sizeof(Datum));
    6966           6 :     ppd->nulls = (char *)
    6967           6 :         MemoryContextAlloc(stmt_mcontext, nargs * sizeof(char));
    6968             : 
    6969           6 :     i = 0;
    6970          15 :     foreach(lc, params)
    6971             :     {
    6972           9 :         PLpgSQL_expr *param = (PLpgSQL_expr *) lfirst(lc);
    6973             :         bool        isnull;
    6974             :         int32       ppdtypmod;
    6975             :         MemoryContext oldcontext;
    6976             : 
    6977          27 :         ppd->values[i] = exec_eval_expr(estate, param,
    6978             :                                         &isnull,
    6979          18 :                                         &ppd->types[i],
    6980             :                                         &ppdtypmod);
    6981           9 :         ppd->nulls[i] = isnull ? 'n' : ' ';
    6982             : 
    6983           9 :         oldcontext = MemoryContextSwitchTo(stmt_mcontext);
    6984             : 
    6985           9 :         if (ppd->types[i] == UNKNOWNOID)
    6986             :         {
    6987             :             /*
    6988             :              * Treat 'unknown' parameters as text, since that's what most
    6989             :              * people would expect. SPI_execute_with_args can coerce unknown
    6990             :              * constants in a more intelligent way, but not unknown Params.
    6991             :              * This code also takes care of copying into the right context.
    6992             :              * Note we assume 'unknown' has the representation of C-string.
    6993             :              */
    6994           0 :             ppd->types[i] = TEXTOID;
    6995           0 :             if (!isnull)
    6996           0 :                 ppd->values[i] = CStringGetTextDatum(DatumGetCString(ppd->values[i]));
    6997             :         }
    6998             :         /* pass-by-ref non null values must be copied into stmt_mcontext */
    6999           9 :         else if (!isnull)
    7000             :         {
    7001             :             int16       typLen;
    7002             :             bool        typByVal;
    7003             : 
    7004           9 :             get_typlenbyval(ppd->types[i], &typLen, &typByVal);
    7005           9 :             if (!typByVal)
    7006           2 :                 ppd->values[i] = datumCopy(ppd->values[i], typByVal, typLen);
    7007             :         }
    7008             : 
    7009           9 :         MemoryContextSwitchTo(oldcontext);
    7010             : 
    7011           9 :         exec_eval_cleanup(estate);
    7012             : 
    7013           9 :         i++;
    7014             :     }
    7015             : 
    7016           6 :     return ppd;
    7017             : }
    7018             : 
    7019             : /*
    7020             :  * Open portal for dynamic query
    7021             :  *
    7022             :  * Caution: this resets the stmt_mcontext at exit.  We might eventually need
    7023             :  * to move that responsibility to the callers, but currently no caller needs
    7024             :  * to have statement-lifetime temp data that survives past this, so it's
    7025             :  * simpler to do it here.
    7026             :  */
    7027             : static Portal
    7028         514 : exec_dynquery_with_params(PLpgSQL_execstate *estate,
    7029             :                           PLpgSQL_expr *dynquery,
    7030             :                           List *params,
    7031             :                           const char *portalname,
    7032             :                           int cursorOptions)
    7033             : {
    7034             :     Portal      portal;
    7035             :     Datum       query;
    7036             :     bool        isnull;
    7037             :     Oid         restype;
    7038             :     int32       restypmod;
    7039             :     char       *querystr;
    7040         514 :     MemoryContext stmt_mcontext = get_stmt_mcontext(estate);
    7041             : 
    7042             :     /*
    7043             :      * Evaluate the string expression after the EXECUTE keyword. Its result is
    7044             :      * the querystring we have to execute.
    7045             :      */
    7046         514 :     query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod);
    7047         514 :     if (isnull)
    7048           0 :         ereport(ERROR,
    7049             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    7050             :                  errmsg("query string argument of EXECUTE is null")));
    7051             : 
    7052             :     /* Get the C-String representation */
    7053         514 :     querystr = convert_value_to_string(estate, query, restype);
    7054             : 
    7055             :     /* copy it into the stmt_mcontext before we clean up */
    7056         514 :     querystr = MemoryContextStrdup(stmt_mcontext, querystr);
    7057             : 
    7058         514 :     exec_eval_cleanup(estate);
    7059             : 
    7060             :     /*
    7061             :      * Open an implicit cursor for the query.  We use
    7062             :      * SPI_cursor_open_with_args even when there are no params, because this
    7063             :      * avoids making and freeing one copy of the plan.
    7064             :      */
    7065         514 :     if (params)
    7066             :     {
    7067             :         PreparedParamsData *ppd;
    7068             : 
    7069           3 :         ppd = exec_eval_using_params(estate, params);
    7070           6 :         portal = SPI_cursor_open_with_args(portalname,
    7071             :                                            querystr,
    7072             :                                            ppd->nargs, ppd->types,
    7073           3 :                                            ppd->values, ppd->nulls,
    7074           3 :                                            estate->readonly_func,
    7075             :                                            cursorOptions);
    7076             :     }
    7077             :     else
    7078             :     {
    7079         511 :         portal = SPI_cursor_open_with_args(portalname,
    7080             :                                            querystr,
    7081             :                                            0, NULL,
    7082             :                                            NULL, NULL,
    7083         511 :                                            estate->readonly_func,
    7084             :                                            cursorOptions);
    7085             :     }
    7086             : 
    7087         514 :     if (portal == NULL)
    7088           0 :         elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
    7089             :              querystr, SPI_result_code_string(SPI_result));
    7090             : 
    7091             :     /* Release transient data */
    7092         514 :     MemoryContextReset(stmt_mcontext);
    7093             : 
    7094         514 :     return portal;
    7095             : }
    7096             : 
    7097             : /*
    7098             :  * Return a formatted string with information about an expression's parameters,
    7099             :  * or NULL if the expression does not take any parameters.
    7100             :  * The result is in the eval_mcontext.
    7101             :  */
    7102             : static char *
    7103           4 : format_expr_params(PLpgSQL_execstate *estate,
    7104             :                    const PLpgSQL_expr *expr)
    7105             : {
    7106             :     int         paramno;
    7107             :     int         dno;
    7108             :     StringInfoData paramstr;
    7109             :     MemoryContext oldcontext;
    7110             : 
    7111           4 :     if (!expr->paramnos)
    7112           1 :         return NULL;
    7113             : 
    7114           3 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    7115             : 
    7116           3 :     initStringInfo(&paramstr);
    7117           3 :     paramno = 0;
    7118           3 :     dno = -1;
    7119          12 :     while ((dno = bms_next_member(expr->paramnos, dno)) >= 0)
    7120             :     {
    7121             :         Datum       paramdatum;
    7122             :         Oid         paramtypeid;
    7123             :         bool        paramisnull;
    7124             :         int32       paramtypmod;
    7125             :         PLpgSQL_var *curvar;
    7126             : 
    7127           6 :         curvar = (PLpgSQL_var *) estate->datums[dno];
    7128             : 
    7129           6 :         exec_eval_datum(estate, (PLpgSQL_datum *) curvar,
    7130             :                         &paramtypeid, &paramtypmod,
    7131             :                         &paramdatum, &paramisnull);
    7132             : 
    7133           6 :         appendStringInfo(&paramstr, "%s%s = ",
    7134             :                          paramno > 0 ? ", " : "",
    7135             :                          curvar->refname);
    7136             : 
    7137           6 :         if (paramisnull)
    7138           0 :             appendStringInfoString(&paramstr, "NULL");
    7139             :         else
    7140             :         {
    7141           6 :             char       *value = convert_value_to_string(estate, paramdatum, paramtypeid);
    7142             :             char       *p;
    7143             : 
    7144           6 :             appendStringInfoCharMacro(&paramstr, '\'');
    7145          18 :             for (p = value; *p; p++)
    7146             :             {
    7147          12 :                 if (*p == '\'') /* double single quotes */
    7148           0 :                     appendStringInfoCharMacro(&paramstr, *p);
    7149          12 :                 appendStringInfoCharMacro(&paramstr, *p);
    7150             :             }
    7151           6 :             appendStringInfoCharMacro(&paramstr, '\'');
    7152             :         }
    7153             : 
    7154           6 :         paramno++;
    7155             :     }
    7156             : 
    7157           3 :     MemoryContextSwitchTo(oldcontext);
    7158             : 
    7159           3 :     return paramstr.data;
    7160             : }
    7161             : 
    7162             : /*
    7163             :  * Return a formatted string with information about PreparedParamsData, or NULL
    7164             :  * if there are no parameters.
    7165             :  * The result is in the eval_mcontext.
    7166             :  */
    7167             : static char *
    7168           3 : format_preparedparamsdata(PLpgSQL_execstate *estate,
    7169             :                           const PreparedParamsData *ppd)
    7170             : {
    7171             :     int         paramno;
    7172             :     StringInfoData paramstr;
    7173             :     MemoryContext oldcontext;
    7174             : 
    7175           3 :     if (!ppd)
    7176           1 :         return NULL;
    7177             : 
    7178           2 :     oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));
    7179             : 
    7180           2 :     initStringInfo(&paramstr);
    7181           5 :     for (paramno = 0; paramno < ppd->nargs; paramno++)
    7182             :     {
    7183           3 :         appendStringInfo(&paramstr, "%s$%d = ",
    7184             :                          paramno > 0 ? ", " : "",
    7185             :                          paramno + 1);
    7186             : 
    7187           3 :         if (ppd->nulls[paramno] == 'n')
    7188           0 :             appendStringInfoString(&paramstr, "NULL");
    7189             :         else
    7190             :         {
    7191           3 :             char       *value = convert_value_to_string(estate, ppd->values[paramno], ppd->types[paramno]);
    7192             :             char       *p;
    7193             : 
    7194           3 :             appendStringInfoCharMacro(&paramstr, '\'');
    7195           8 :             for (p = value; *p; p++)
    7196             :             {
    7197           5 :                 if (*p == '\'') /* double single quotes */
    7198           0 :                     appendStringInfoCharMacro(&paramstr, *p);
    7199           5 :                 appendStringInfoCharMacro(&paramstr, *p);
    7200             :             }
    7201           3 :             appendStringInfoCharMacro(&paramstr, '\'');
    7202             :         }
    7203             :     }
    7204             : 
    7205           2 :     MemoryContextSwitchTo(oldcontext);
    7206             : 
    7207           2 :     return paramstr.data;
    7208             : }

Generated by: LCOV version 1.11