~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

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

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
 * pl_comp.c            - Compiler part of the PL/pgSQL
 
3
 *                        procedural language
 
4
 *
 
5
 * IDENTIFICATION
 
6
 *        $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.83 2004-11-30 03:50:29 neilc Exp $
 
7
 *
 
8
 *        This software is copyrighted by Jan Wieck - Hamburg.
 
9
 *
 
10
 *        The author hereby grants permission  to  use,  copy,  modify,
 
11
 *        distribute,  and      license this software and its documentation
 
12
 *        for any purpose, provided that existing copyright notices are
 
13
 *        retained      in      all  copies  and  that  this notice is included
 
14
 *        verbatim in any distributions. No written agreement, license,
 
15
 *        or  royalty  fee      is required for any of the authorized uses.
 
16
 *        Modifications to this software may be  copyrighted  by  their
 
17
 *        author  and  need  not  follow  the licensing terms described
 
18
 *        here, provided that the new terms are  clearly  indicated  on
 
19
 *        the first page of each file where they apply.
 
20
 *
 
21
 *        IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
 
22
 *        PARTY  FOR  DIRECT,   INDIRECT,       SPECIAL,   INCIDENTAL,   OR
 
23
 *        CONSEQUENTIAL   DAMAGES  ARISING      OUT  OF  THE  USE  OF  THIS
 
24
 *        SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
 
25
 *        IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 
26
 *        DAMAGE.
 
27
 *
 
28
 *        THE  AUTHOR  AND      DISTRIBUTORS  SPECIFICALLY       DISCLAIM       ANY
 
29
 *        WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
 
30
 *        WARRANTIES  OF  MERCHANTABILITY,      FITNESS  FOR  A  PARTICULAR
 
31
 *        PURPOSE,      AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
 
32
 *        AN "AS IS" BASIS, AND THE AUTHOR      AND  DISTRIBUTORS  HAVE  NO
 
33
 *        OBLIGATION   TO       PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
 
34
 *        ENHANCEMENTS, OR MODIFICATIONS.
 
35
 *
 
36
 **********************************************************************/
 
37
 
 
38
#include "plpgsql.h"
 
39
 
 
40
#include <ctype.h>
 
41
 
 
42
#include "pl.tab.h"
 
43
 
 
44
#include "access/heapam.h"
 
45
#include "catalog/catname.h"
 
46
#include "catalog/namespace.h"
 
47
#include "catalog/pg_attribute.h"
 
48
#include "catalog/pg_attrdef.h"
 
49
#include "catalog/pg_class.h"
 
50
#include "catalog/pg_proc.h"
 
51
#include "catalog/pg_type.h"
 
52
#include "nodes/makefuncs.h"
 
53
#include "parser/gramparse.h"
 
54
#include "parser/parse_type.h"
 
55
#include "tcop/tcopprot.h"
 
56
#include "utils/array.h"
 
57
#include "utils/builtins.h"
 
58
#include "utils/lsyscache.h"
 
59
#include "utils/syscache.h"
 
60
 
 
61
 
 
62
/* ----------
 
63
 * Variables in the parser that shouldn't go into plpgsql.h
 
64
 * ----------
 
65
 */
 
66
extern PLPGSQL_YYSTYPE plpgsql_yylval;
 
67
 
 
68
/* ----------
 
69
 * Our own local and global variables
 
70
 * ----------
 
71
 */
 
72
static int      datums_alloc;
 
73
int                     plpgsql_nDatums;
 
74
PLpgSQL_datum **plpgsql_Datums;
 
75
static int      datums_last = 0;
 
76
 
 
77
int                     plpgsql_error_lineno;
 
78
char       *plpgsql_error_funcname;
 
79
int                     plpgsql_DumpExecTree = 0;
 
80
 
 
81
PLpgSQL_function *plpgsql_curr_compile;
 
82
 
 
83
/* ----------
 
84
 * Hash table for compiled functions
 
85
 * ----------
 
86
 */
 
87
static HTAB *plpgsql_HashTable = NULL;
 
88
 
 
89
typedef struct plpgsql_hashent
 
90
{
 
91
        PLpgSQL_func_hashkey key;
 
92
        PLpgSQL_function *function;
 
93
} plpgsql_HashEnt;
 
94
 
 
95
#define FUNCS_PER_USER          128 /* initial table size */
 
96
 
 
97
/* ----------
 
98
 * Lookup table for EXCEPTION condition names
 
99
 * ----------
 
100
 */
 
101
typedef struct
 
102
{
 
103
        const char *label;
 
104
        int                     sqlerrstate;
 
105
} ExceptionLabelMap;
 
106
 
 
107
static const ExceptionLabelMap exception_label_map[] = {
 
108
#include "plerrcodes.h"
 
109
        {NULL, 0}
 
110
};
 
111
 
 
112
 
 
113
/* ----------
 
114
 * static prototypes
 
115
 * ----------
 
116
 */
 
117
static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
 
118
                   HeapTuple procTup,
 
119
                   PLpgSQL_func_hashkey *hashkey,
 
120
                   bool forValidator);
 
121
static void plpgsql_compile_error_callback(void *arg);
 
122
static char **fetchArgNames(HeapTuple procTup, int nargs);
 
123
static PLpgSQL_row *build_row_var(Oid classOid);
 
124
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
 
125
static void compute_function_hashkey(FunctionCallInfo fcinfo,
 
126
                                                 Form_pg_proc procStruct,
 
127
                                                 PLpgSQL_func_hashkey *hashkey,
 
128
                                                 bool forValidator);
 
129
static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
 
130
static void plpgsql_HashTableInsert(PLpgSQL_function *function,
 
131
                                                PLpgSQL_func_hashkey *func_key);
 
132
static void plpgsql_HashTableDelete(PLpgSQL_function *function);
 
133
 
 
134
/*
 
135
 * This routine is a crock, and so is everyplace that calls it.  The problem
 
136
 * is that the compiled form of a plpgsql function is allocated permanently
 
137
 * (mostly via malloc()) and never released until backend exit.  Subsidiary
 
138
 * data structures such as fmgr info records therefore must live forever
 
139
 * as well.  A better implementation would store all this stuff in a per-
 
140
 * function memory context that could be reclaimed at need.  In the meantime,
 
141
 * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
 
142
 * it might allocate, and whatever the eventual function might allocate using
 
143
 * fn_mcxt, will live forever too.
 
144
 */
 
145
static void
 
146
perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 
147
{
 
148
        fmgr_info_cxt(functionId, finfo, TopMemoryContext);
 
149
}
 
150
 
 
151
 
 
152
/* ----------
 
153
 * plpgsql_compile              Make an execution tree for a PL/pgSQL function.
 
154
 *
 
155
 * If forValidator is true, we're only compiling for validation purposes,
 
156
 * and so some checks are skipped.
 
157
 *
 
158
 * Note: it's important for this to fall through quickly if the function
 
159
 * has already been compiled.
 
160
 * ----------
 
161
 */
 
162
PLpgSQL_function *
 
163
plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
 
164
{
 
165
        Oid                     funcOid = fcinfo->flinfo->fn_oid;
 
166
        HeapTuple       procTup;
 
167
        Form_pg_proc procStruct;
 
168
        PLpgSQL_function *function;
 
169
        PLpgSQL_func_hashkey hashkey;
 
170
        bool            hashkey_valid = false;
 
171
 
 
172
        /*
 
173
         * Lookup the pg_proc tuple by Oid; we'll need it in any case
 
174
         */
 
175
        procTup = SearchSysCache(PROCOID,
 
176
                                                         ObjectIdGetDatum(funcOid),
 
177
                                                         0, 0, 0);
 
178
        if (!HeapTupleIsValid(procTup))
 
179
                elog(ERROR, "cache lookup failed for function %u", funcOid);
 
180
        procStruct = (Form_pg_proc) GETSTRUCT(procTup);
 
181
 
 
182
        /*
 
183
         * See if there's already a cache entry for the current FmgrInfo. If
 
184
         * not, try to find one in the hash table.
 
185
         */
 
186
        function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
 
187
 
 
188
        if (!function)
 
189
        {
 
190
                /* First time through in this backend?  If so, init hashtable */
 
191
                if (!plpgsql_HashTable)
 
192
                        plpgsql_HashTableInit();
 
193
 
 
194
                /* Compute hashkey using function signature and actual arg types */
 
195
                compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
 
196
                hashkey_valid = true;
 
197
 
 
198
                /* And do the lookup */
 
199
                function = plpgsql_HashTableLookup(&hashkey);
 
200
        }
 
201
 
 
202
        if (function)
 
203
        {
 
204
                /* We have a compiled function, but is it still valid? */
 
205
                if (!(function->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
 
206
                   function->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data)))
 
207
                {
 
208
                        /*
 
209
                         * Nope, drop the hashtable entry.      XXX someday, free all the
 
210
                         * subsidiary storage as well.
 
211
                         */
 
212
                        plpgsql_HashTableDelete(function);
 
213
 
 
214
                        function = NULL;
 
215
                }
 
216
        }
 
217
 
 
218
        /*
 
219
         * If the function wasn't found or was out-of-date, we have to compile
 
220
         * it
 
221
         */
 
222
        if (!function)
 
223
        {
 
224
                /*
 
225
                 * Calculate hashkey if we didn't already; we'll need it to store
 
226
                 * the completed function.
 
227
                 */
 
228
                if (!hashkey_valid)
 
229
                        compute_function_hashkey(fcinfo, procStruct, &hashkey,
 
230
                                                                         forValidator);
 
231
 
 
232
                /*
 
233
                 * Do the hard part.
 
234
                 */
 
235
                function = do_compile(fcinfo, procTup, &hashkey, forValidator);
 
236
        }
 
237
 
 
238
        ReleaseSysCache(procTup);
 
239
 
 
240
        /*
 
241
         * Save pointer in FmgrInfo to avoid search on subsequent calls
 
242
         */
 
243
        fcinfo->flinfo->fn_extra = (void *) function;
 
244
 
 
245
        /*
 
246
         * Finally return the compiled function
 
247
         */
 
248
        return function;
 
249
}
 
250
 
 
251
/*
 
252
 * This is the slow part of plpgsql_compile().
 
253
 */
 
254
static PLpgSQL_function *
 
255
do_compile(FunctionCallInfo fcinfo,
 
256
                   HeapTuple procTup,
 
257
                   PLpgSQL_func_hashkey *hashkey,
 
258
                   bool forValidator)
 
259
{
 
260
        Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
 
261
        int                     functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
 
262
        PLpgSQL_function *function;
 
263
        Datum           prosrcdatum;
 
264
        bool            isnull;
 
265
        char       *proc_source;
 
266
        HeapTuple       typeTup;
 
267
        Form_pg_type typeStruct;
 
268
        PLpgSQL_variable *var;
 
269
        PLpgSQL_rec *rec;
 
270
        int                     i;
 
271
        int                     arg_varnos[FUNC_MAX_ARGS];
 
272
        ErrorContextCallback plerrcontext;
 
273
        int                     parse_rc;
 
274
        Oid                     rettypeid;
 
275
        char      **argnames;
 
276
 
 
277
        /*
 
278
         * Setup the scanner input and error info.      We assume that this
 
279
         * function cannot be invoked recursively, so there's no need to save
 
280
         * and restore the static variables used here.
 
281
         */
 
282
        prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
 
283
                                                                  Anum_pg_proc_prosrc, &isnull);
 
284
        if (isnull)
 
285
                elog(ERROR, "null prosrc");
 
286
        proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
 
287
        plpgsql_scanner_init(proc_source, functype);
 
288
 
 
289
        plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
 
290
        plpgsql_error_lineno = 0;
 
291
 
 
292
        /*
 
293
         * Setup error traceback support for ereport()
 
294
         */
 
295
        plerrcontext.callback = plpgsql_compile_error_callback;
 
296
        plerrcontext.arg = forValidator ? proc_source : (char *) NULL;
 
297
        plerrcontext.previous = error_context_stack;
 
298
        error_context_stack = &plerrcontext;
 
299
 
 
300
        /*
 
301
         * Initialize the compiler
 
302
         */
 
303
        plpgsql_ns_init();
 
304
        plpgsql_ns_push(NULL);
 
305
        plpgsql_DumpExecTree = 0;
 
306
 
 
307
        datums_alloc = 128;
 
308
        plpgsql_nDatums = 0;
 
309
        plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
 
310
        datums_last = 0;
 
311
 
 
312
        /*
 
313
         * Create the new function node
 
314
         */
 
315
        function = malloc(sizeof(PLpgSQL_function));
 
316
        MemSet(function, 0, sizeof(PLpgSQL_function));
 
317
        plpgsql_curr_compile = function;
 
318
 
 
319
        function->fn_name = strdup(NameStr(procStruct->proname));
 
320
        function->fn_oid = fcinfo->flinfo->fn_oid;
 
321
        function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
 
322
        function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
 
323
        function->fn_functype = functype;
 
324
 
 
325
        switch (functype)
 
326
        {
 
327
                case T_FUNCTION:
 
328
 
 
329
                        /*
 
330
                         * Check for a polymorphic returntype. If found, use the
 
331
                         * actual returntype type from the caller's FuncExpr node, if
 
332
                         * we have one.  (In validation mode we arbitrarily assume we
 
333
                         * are dealing with integers.)
 
334
                         *
 
335
                         * Note: errcode is FEATURE_NOT_SUPPORTED because it should
 
336
                         * always work; if it doesn't we're in some context that fails
 
337
                         * to make the info available.
 
338
                         */
 
339
                        rettypeid = procStruct->prorettype;
 
340
                        if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
 
341
                        {
 
342
                                if (forValidator)
 
343
                                {
 
344
                                        if (rettypeid == ANYARRAYOID)
 
345
                                                rettypeid = INT4ARRAYOID;
 
346
                                        else
 
347
                                                rettypeid = INT4OID;
 
348
                                }
 
349
                                else
 
350
                                        rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
 
351
                                if (!OidIsValid(rettypeid))
 
352
                                        ereport(ERROR,
 
353
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
354
                                                 errmsg("could not determine actual return type "
 
355
                                                                "for polymorphic function \"%s\"",
 
356
                                                                plpgsql_error_funcname)));
 
357
                        }
 
358
 
 
359
                        /*
 
360
                         * Normal function has a defined returntype
 
361
                         */
 
362
                        function->fn_rettype = rettypeid;
 
363
                        function->fn_retset = procStruct->proretset;
 
364
 
 
365
                        /*
 
366
                         * Lookup the function's return type
 
367
                         */
 
368
                        typeTup = SearchSysCache(TYPEOID,
 
369
                                                                         ObjectIdGetDatum(rettypeid),
 
370
                                                                         0, 0, 0);
 
371
                        if (!HeapTupleIsValid(typeTup))
 
372
                                elog(ERROR, "cache lookup failed for type %u", rettypeid);
 
373
                        typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 
374
 
 
375
                        /* Disallow pseudotype result, except VOID or RECORD */
 
376
                        /* (note we already replaced ANYARRAY/ANYELEMENT) */
 
377
                        if (typeStruct->typtype == 'p')
 
378
                        {
 
379
                                if (rettypeid == VOIDOID ||
 
380
                                        rettypeid == RECORDOID)
 
381
                                         /* okay */ ;
 
382
                                else if (rettypeid == TRIGGEROID)
 
383
                                        ereport(ERROR,
 
384
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
385
                                                         errmsg("trigger functions may only be called as triggers")));
 
386
                                else
 
387
                                        ereport(ERROR,
 
388
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
389
                                                errmsg("plpgsql functions cannot return type %s",
 
390
                                                           format_type_be(rettypeid))));
 
391
                        }
 
392
 
 
393
                        if (typeStruct->typrelid != InvalidOid ||
 
394
                                rettypeid == RECORDOID)
 
395
                                function->fn_retistuple = true;
 
396
                        else
 
397
                        {
 
398
                                function->fn_retbyval = typeStruct->typbyval;
 
399
                                function->fn_rettyplen = typeStruct->typlen;
 
400
                                function->fn_rettypioparam = getTypeIOParam(typeTup);
 
401
                                perm_fmgr_info(typeStruct->typinput, &(function->fn_retinput));
 
402
 
 
403
                                /*
 
404
                                 * install $0 reference, but only for polymorphic return
 
405
                                 * types
 
406
                                 */
 
407
                                if (procStruct->prorettype == ANYARRAYOID ||
 
408
                                        procStruct->prorettype == ANYELEMENTOID)
 
409
                                {
 
410
                                        (void) plpgsql_build_variable(strdup("$0"), 0,
 
411
                                                                                         build_datatype(typeTup, -1),
 
412
                                                                                                  true);
 
413
                                }
 
414
                        }
 
415
                        ReleaseSysCache(typeTup);
 
416
 
 
417
                        /*
 
418
                         * Create the variables for the procedure's parameters
 
419
                         */
 
420
                        argnames = fetchArgNames(procTup, procStruct->pronargs);
 
421
 
 
422
                        for (i = 0; i < procStruct->pronargs; i++)
 
423
                        {
 
424
                                char            buf[32];
 
425
                                Oid                     argtypeid;
 
426
                                PLpgSQL_type *argdtype;
 
427
                                PLpgSQL_variable *argvariable;
 
428
                                int                     argitemtype;
 
429
 
 
430
                                /* Create $n name for variable */
 
431
                                snprintf(buf, sizeof(buf), "$%d", i + 1);
 
432
 
 
433
                                /*
 
434
                                 * Since we already did the replacement of polymorphic
 
435
                                 * argument types by actual argument types while computing
 
436
                                 * the hashkey, we can just use those results.
 
437
                                 */
 
438
                                argtypeid = hashkey->argtypes[i];
 
439
                                argdtype = plpgsql_build_datatype(argtypeid, -1);
 
440
 
 
441
                                /* Disallow pseudotype argument */
 
442
                                /* (note we already replaced ANYARRAY/ANYELEMENT) */
 
443
                                /* (build_variable would do this, but wrong message) */
 
444
                                if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
 
445
                                        argdtype->ttype != PLPGSQL_TTYPE_ROW)
 
446
                                        ereport(ERROR,
 
447
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
448
                                                  errmsg("plpgsql functions cannot take type %s",
 
449
                                                                 format_type_be(argtypeid))));
 
450
 
 
451
                                /* Build variable and add to datum list */
 
452
                                argvariable = plpgsql_build_variable(strdup(buf), 0,
 
453
                                                                                                         argdtype, false);
 
454
 
 
455
                                if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
 
456
                                {
 
457
                                        /* argument vars are forced to be CONSTANT (why?) */
 
458
                                        ((PLpgSQL_var *) argvariable)->isconst = true;
 
459
                                        argitemtype = PLPGSQL_NSTYPE_VAR;
 
460
                                }
 
461
                                else
 
462
                                {
 
463
                                        Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
 
464
                                        argitemtype = PLPGSQL_NSTYPE_ROW;
 
465
                                }
 
466
 
 
467
                                /* Remember datum number */
 
468
                                arg_varnos[i] = argvariable->dno;
 
469
 
 
470
                                /* Add to namespace under the $n name */
 
471
                                plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
 
472
 
 
473
                                /* If there's a name for the argument, make an alias */
 
474
                                if (argnames && argnames[i] && argnames[i][0])
 
475
                                        plpgsql_ns_additem(argitemtype, argvariable->dno,
 
476
                                                                           argnames[i]);
 
477
                        }
 
478
                        break;
 
479
 
 
480
                case T_TRIGGER:
 
481
 
 
482
                        /*
 
483
                         * Trigger procedures return type is unknown yet
 
484
                         */
 
485
                        function->fn_rettype = InvalidOid;
 
486
                        function->fn_retbyval = false;
 
487
                        function->fn_retistuple = true;
 
488
                        function->fn_retset = false;
 
489
 
 
490
                        /*
 
491
                         * Add the record for referencing NEW
 
492
                         */
 
493
                        rec = malloc(sizeof(PLpgSQL_rec));
 
494
                        memset(rec, 0, sizeof(PLpgSQL_rec));
 
495
                        rec->dtype = PLPGSQL_DTYPE_REC;
 
496
                        rec->refname = strdup("new");
 
497
                        rec->tup = NULL;
 
498
                        rec->tupdesc = NULL;
 
499
                        rec->freetup = false;
 
500
                        plpgsql_adddatum((PLpgSQL_datum *) rec);
 
501
                        plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
 
502
                        function->new_varno = rec->recno;
 
503
 
 
504
                        /*
 
505
                         * Add the record for referencing OLD
 
506
                         */
 
507
                        rec = malloc(sizeof(PLpgSQL_rec));
 
508
                        memset(rec, 0, sizeof(PLpgSQL_rec));
 
509
                        rec->dtype = PLPGSQL_DTYPE_REC;
 
510
                        rec->refname = strdup("old");
 
511
                        rec->tup = NULL;
 
512
                        rec->tupdesc = NULL;
 
513
                        rec->freetup = false;
 
514
                        plpgsql_adddatum((PLpgSQL_datum *) rec);
 
515
                        plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
 
516
                        function->old_varno = rec->recno;
 
517
 
 
518
                        /*
 
519
                         * Add the variable tg_name
 
520
                         */
 
521
                        var = plpgsql_build_variable(strdup("tg_name"), 0,
 
522
                                                                         plpgsql_build_datatype(NAMEOID, -1),
 
523
                                                                                 true);
 
524
                        function->tg_name_varno = var->dno;
 
525
 
 
526
                        /*
 
527
                         * Add the variable tg_when
 
528
                         */
 
529
                        var = plpgsql_build_variable(strdup("tg_when"), 0,
 
530
                                                                         plpgsql_build_datatype(TEXTOID, -1),
 
531
                                                                                 true);
 
532
                        function->tg_when_varno = var->dno;
 
533
 
 
534
                        /*
 
535
                         * Add the variable tg_level
 
536
                         */
 
537
                        var = plpgsql_build_variable(strdup("tg_level"), 0,
 
538
                                                                         plpgsql_build_datatype(TEXTOID, -1),
 
539
                                                                                 true);
 
540
                        function->tg_level_varno = var->dno;
 
541
 
 
542
                        /*
 
543
                         * Add the variable tg_op
 
544
                         */
 
545
                        var = plpgsql_build_variable(strdup("tg_op"), 0,
 
546
                                                                         plpgsql_build_datatype(TEXTOID, -1),
 
547
                                                                                 true);
 
548
                        function->tg_op_varno = var->dno;
 
549
 
 
550
                        /*
 
551
                         * Add the variable tg_relid
 
552
                         */
 
553
                        var = plpgsql_build_variable(strdup("tg_relid"), 0,
 
554
                                                                          plpgsql_build_datatype(OIDOID, -1),
 
555
                                                                                 true);
 
556
                        function->tg_relid_varno = var->dno;
 
557
 
 
558
                        /*
 
559
                         * Add the variable tg_relname
 
560
                         */
 
561
                        var = plpgsql_build_variable(strdup("tg_relname"), 0,
 
562
                                                                         plpgsql_build_datatype(NAMEOID, -1),
 
563
                                                                                 true);
 
564
                        function->tg_relname_varno = var->dno;
 
565
 
 
566
                        /*
 
567
                         * Add the variable tg_nargs
 
568
                         */
 
569
                        var = plpgsql_build_variable(strdup("tg_nargs"), 0,
 
570
                                                                         plpgsql_build_datatype(INT4OID, -1),
 
571
                                                                                 true);
 
572
                        function->tg_nargs_varno = var->dno;
 
573
 
 
574
                        break;
 
575
 
 
576
                default:
 
577
                        elog(ERROR, "unrecognized function typecode: %u", functype);
 
578
                        break;
 
579
        }
 
580
 
 
581
        /* Remember if function is STABLE/IMMUTABLE */
 
582
        function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
 
583
 
 
584
        /*
 
585
         * Create the magic FOUND variable.
 
586
         */
 
587
        var = plpgsql_build_variable(strdup("found"), 0,
 
588
                                                                 plpgsql_build_datatype(BOOLOID, -1),
 
589
                                                                 true);
 
590
        function->found_varno = var->dno;
 
591
 
 
592
        /*
 
593
         * Forget about the above created variables
 
594
         */
 
595
        plpgsql_add_initdatums(NULL);
 
596
 
 
597
        /*
 
598
         * Now parse the function's text
 
599
         */
 
600
        parse_rc = plpgsql_yyparse();
 
601
        if (parse_rc != 0)
 
602
                elog(ERROR, "plpgsql parser returned %d", parse_rc);
 
603
 
 
604
        plpgsql_scanner_finish();
 
605
        pfree(proc_source);
 
606
 
 
607
        /*
 
608
         * If that was successful, complete the function's info.
 
609
         */
 
610
        function->fn_nargs = procStruct->pronargs;
 
611
        for (i = 0; i < function->fn_nargs; i++)
 
612
                function->fn_argvarnos[i] = arg_varnos[i];
 
613
        function->ndatums = plpgsql_nDatums;
 
614
        function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
 
615
        for (i = 0; i < plpgsql_nDatums; i++)
 
616
                function->datums[i] = plpgsql_Datums[i];
 
617
        function->action = plpgsql_yylval.program;
 
618
 
 
619
        /* Debug dump for completed functions */
 
620
        if (plpgsql_DumpExecTree)
 
621
                plpgsql_dumptree(function);
 
622
 
 
623
        /*
 
624
         * add it to the hash table
 
625
         */
 
626
        plpgsql_HashTableInsert(function, hashkey);
 
627
 
 
628
        /*
 
629
         * Pop the error context stack
 
630
         */
 
631
        error_context_stack = plerrcontext.previous;
 
632
        plpgsql_error_funcname = NULL;
 
633
        plpgsql_error_lineno = 0;
 
634
 
 
635
        return function;
 
636
}
 
637
 
 
638
 
 
639
/*
 
640
 * error context callback to let us supply a call-stack traceback
 
641
 *
 
642
 * If we are validating, the function source is passed as argument.
 
643
 */
 
644
static void
 
645
plpgsql_compile_error_callback(void *arg)
 
646
{
 
647
        if (arg)
 
648
        {
 
649
                /*
 
650
                 * Try to convert syntax error position to reference text of
 
651
                 * original CREATE FUNCTION command.
 
652
                 */
 
653
                if (function_parse_error_transpose((const char *) arg))
 
654
                        return;
 
655
 
 
656
                /*
 
657
                 * Done if a syntax error position was reported; otherwise we have
 
658
                 * to fall back to a "near line N" report.
 
659
                 */
 
660
        }
 
661
 
 
662
        if (plpgsql_error_funcname)
 
663
                errcontext("compile of PL/pgSQL function \"%s\" near line %d",
 
664
                                   plpgsql_error_funcname, plpgsql_error_lineno);
 
665
}
 
666
 
 
667
 
 
668
/*
 
669
 * Fetch the argument names, if any, from the proargnames field of the
 
670
 * pg_proc tuple.  Results are palloc'd.
 
671
 */
 
672
static char **
 
673
fetchArgNames(HeapTuple procTup, int nargs)
 
674
{
 
675
        Datum           argnamesDatum;
 
676
        bool            isNull;
 
677
        Datum      *elems;
 
678
        int                     nelems;
 
679
        char      **result;
 
680
        int                     i;
 
681
 
 
682
        if (nargs == 0)
 
683
                return NULL;
 
684
 
 
685
        argnamesDatum = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames,
 
686
                                                                        &isNull);
 
687
        if (isNull)
 
688
                return NULL;
 
689
 
 
690
        deconstruct_array(DatumGetArrayTypeP(argnamesDatum),
 
691
                                          TEXTOID, -1, false, 'i',
 
692
                                          &elems, &nelems);
 
693
 
 
694
        if (nelems != nargs)            /* should not happen */
 
695
                elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
 
696
 
 
697
        result = (char **) palloc(sizeof(char *) * nargs);
 
698
 
 
699
        for (i = 0; i < nargs; i++)
 
700
                result[i] = DatumGetCString(DirectFunctionCall1(textout, elems[i]));
 
701
 
 
702
        return result;
 
703
}
 
704
 
 
705
 
 
706
/* ----------
 
707
 * plpgsql_parse_word           The scanner calls this to postparse
 
708
 *                              any single word not found by a
 
709
 *                              keyword rule.
 
710
 * ----------
 
711
 */
 
712
int
 
713
plpgsql_parse_word(char *word)
 
714
{
 
715
        PLpgSQL_nsitem *nse;
 
716
        char       *cp[1];
 
717
 
 
718
        /* Do case conversion and word separation */
 
719
        plpgsql_convert_ident(word, cp, 1);
 
720
 
 
721
        /*
 
722
         * Recognize tg_argv when compiling triggers
 
723
         */
 
724
        if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
 
725
        {
 
726
                if (strcmp(cp[0], "tg_argv") == 0)
 
727
                {
 
728
                        int                     save_spacescanned = plpgsql_SpaceScanned;
 
729
                        PLpgSQL_trigarg *trigarg;
 
730
 
 
731
                        trigarg = malloc(sizeof(PLpgSQL_trigarg));
 
732
                        memset(trigarg, 0, sizeof(PLpgSQL_trigarg));
 
733
                        trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
 
734
 
 
735
                        if (plpgsql_yylex() != '[')
 
736
                                plpgsql_yyerror("expected \"[\"");
 
737
 
 
738
                        trigarg->argnum = plpgsql_read_expression(']', "]");
 
739
 
 
740
                        plpgsql_adddatum((PLpgSQL_datum *) trigarg);
 
741
                        plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
 
742
 
 
743
                        plpgsql_SpaceScanned = save_spacescanned;
 
744
                        pfree(cp[0]);
 
745
                        return T_SCALAR;
 
746
                }
 
747
        }
 
748
 
 
749
        /*
 
750
         * Do a lookup on the compilers namestack
 
751
         */
 
752
        nse = plpgsql_ns_lookup(cp[0], NULL);
 
753
        if (nse != NULL)
 
754
        {
 
755
                pfree(cp[0]);
 
756
                switch (nse->itemtype)
 
757
                {
 
758
                        case PLPGSQL_NSTYPE_LABEL:
 
759
                                return T_LABEL;
 
760
 
 
761
                        case PLPGSQL_NSTYPE_VAR:
 
762
                                plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
 
763
                                return T_SCALAR;
 
764
 
 
765
                        case PLPGSQL_NSTYPE_REC:
 
766
                                plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
 
767
                                return T_RECORD;
 
768
 
 
769
                        case PLPGSQL_NSTYPE_ROW:
 
770
                                plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
 
771
                                return T_ROW;
 
772
 
 
773
                        default:
 
774
                                return T_ERROR;
 
775
                }
 
776
        }
 
777
 
 
778
        /*
 
779
         * Nothing found - up to now it's a word without any special meaning
 
780
         * for us.
 
781
         */
 
782
        pfree(cp[0]);
 
783
        return T_WORD;
 
784
}
 
785
 
 
786
 
 
787
/* ----------
 
788
 * plpgsql_parse_dblword                Same lookup for two words
 
789
 *                                      separated by a dot.
 
790
 * ----------
 
791
 */
 
792
int
 
793
plpgsql_parse_dblword(char *word)
 
794
{
 
795
        PLpgSQL_nsitem *ns;
 
796
        char       *cp[2];
 
797
 
 
798
        /* Do case conversion and word separation */
 
799
        plpgsql_convert_ident(word, cp, 2);
 
800
 
 
801
        /*
 
802
         * Lookup the first word
 
803
         */
 
804
        ns = plpgsql_ns_lookup(cp[0], NULL);
 
805
        if (ns == NULL)
 
806
        {
 
807
                pfree(cp[0]);
 
808
                pfree(cp[1]);
 
809
                return T_ERROR;
 
810
        }
 
811
 
 
812
        switch (ns->itemtype)
 
813
        {
 
814
                case PLPGSQL_NSTYPE_LABEL:
 
815
 
 
816
                        /*
 
817
                         * First word is a label, so second word could be a variable,
 
818
                         * record or row in that bodies namestack. Anything else could
 
819
                         * only be something in a query given to the SPI manager and
 
820
                         * T_ERROR will get eaten up by the collector routines.
 
821
                         */
 
822
                        ns = plpgsql_ns_lookup(cp[1], cp[0]);
 
823
                        pfree(cp[0]);
 
824
                        pfree(cp[1]);
 
825
                        if (ns == NULL)
 
826
                                return T_ERROR;
 
827
                        switch (ns->itemtype)
 
828
                        {
 
829
                                case PLPGSQL_NSTYPE_VAR:
 
830
                                        plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
 
831
                                        return T_SCALAR;
 
832
 
 
833
                                case PLPGSQL_NSTYPE_REC:
 
834
                                        plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
 
835
                                        return T_RECORD;
 
836
 
 
837
                                case PLPGSQL_NSTYPE_ROW:
 
838
                                        plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
 
839
                                        return T_ROW;
 
840
 
 
841
                                default:
 
842
                                        return T_ERROR;
 
843
                        }
 
844
                        break;
 
845
 
 
846
                case PLPGSQL_NSTYPE_REC:
 
847
                        {
 
848
                                /*
 
849
                                 * First word is a record name, so second word must be a
 
850
                                 * field in this record.
 
851
                                 */
 
852
                                PLpgSQL_recfield *new;
 
853
 
 
854
                                new = malloc(sizeof(PLpgSQL_recfield));
 
855
                                new->dtype = PLPGSQL_DTYPE_RECFIELD;
 
856
                                new->fieldname = strdup(cp[1]);
 
857
                                new->recparentno = ns->itemno;
 
858
 
 
859
                                plpgsql_adddatum((PLpgSQL_datum *) new);
 
860
 
 
861
                                plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
 
862
 
 
863
                                pfree(cp[0]);
 
864
                                pfree(cp[1]);
 
865
                                return T_SCALAR;
 
866
                        }
 
867
 
 
868
                case PLPGSQL_NSTYPE_ROW:
 
869
                        {
 
870
                                /*
 
871
                                 * First word is a row name, so second word must be a
 
872
                                 * field in this row.
 
873
                                 */
 
874
                                PLpgSQL_row *row;
 
875
                                int                     i;
 
876
 
 
877
                                row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
 
878
                                for (i = 0; i < row->nfields; i++)
 
879
                                {
 
880
                                        if (row->fieldnames[i] &&
 
881
                                                strcmp(row->fieldnames[i], cp[1]) == 0)
 
882
                                        {
 
883
                                                plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
 
884
                                                pfree(cp[0]);
 
885
                                                pfree(cp[1]);
 
886
                                                return T_SCALAR;
 
887
                                        }
 
888
                                }
 
889
                                ereport(ERROR,
 
890
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
891
                                                 errmsg("row \"%s\" has no field \"%s\"",
 
892
                                                                cp[0], cp[1])));
 
893
                        }
 
894
 
 
895
                default:
 
896
                        break;
 
897
        }
 
898
 
 
899
        pfree(cp[0]);
 
900
        pfree(cp[1]);
 
901
        return T_ERROR;
 
902
}
 
903
 
 
904
 
 
905
/* ----------
 
906
 * plpgsql_parse_tripword               Same lookup for three words
 
907
 *                                      separated by dots.
 
908
 * ----------
 
909
 */
 
910
int
 
911
plpgsql_parse_tripword(char *word)
 
912
{
 
913
        PLpgSQL_nsitem *ns;
 
914
        char       *cp[3];
 
915
 
 
916
        /* Do case conversion and word separation */
 
917
        plpgsql_convert_ident(word, cp, 3);
 
918
 
 
919
        /*
 
920
         * Lookup the first word - it must be a label
 
921
         */
 
922
        ns = plpgsql_ns_lookup(cp[0], NULL);
 
923
        if (ns == NULL)
 
924
        {
 
925
                pfree(cp[0]);
 
926
                pfree(cp[1]);
 
927
                pfree(cp[2]);
 
928
                return T_ERROR;
 
929
        }
 
930
        if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
 
931
        {
 
932
                pfree(cp[0]);
 
933
                pfree(cp[1]);
 
934
                pfree(cp[2]);
 
935
                return T_ERROR;
 
936
        }
 
937
 
 
938
        /*
 
939
         * First word is a label, so second word could be a record or row
 
940
         */
 
941
        ns = plpgsql_ns_lookup(cp[1], cp[0]);
 
942
        if (ns == NULL)
 
943
        {
 
944
                pfree(cp[0]);
 
945
                pfree(cp[1]);
 
946
                pfree(cp[2]);
 
947
                return T_ERROR;
 
948
        }
 
949
 
 
950
        switch (ns->itemtype)
 
951
        {
 
952
                case PLPGSQL_NSTYPE_REC:
 
953
                        {
 
954
                                /*
 
955
                                 * This word is a record name, so third word must be a
 
956
                                 * field in this record.
 
957
                                 */
 
958
                                PLpgSQL_recfield *new;
 
959
 
 
960
                                new = malloc(sizeof(PLpgSQL_recfield));
 
961
                                new->dtype = PLPGSQL_DTYPE_RECFIELD;
 
962
                                new->fieldname = strdup(cp[2]);
 
963
                                new->recparentno = ns->itemno;
 
964
 
 
965
                                plpgsql_adddatum((PLpgSQL_datum *) new);
 
966
 
 
967
                                plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
 
968
 
 
969
                                pfree(cp[0]);
 
970
                                pfree(cp[1]);
 
971
                                pfree(cp[2]);
 
972
 
 
973
                                return T_SCALAR;
 
974
                        }
 
975
 
 
976
                case PLPGSQL_NSTYPE_ROW:
 
977
                        {
 
978
                                /*
 
979
                                 * This word is a row name, so third word must be a field
 
980
                                 * in this row.
 
981
                                 */
 
982
                                PLpgSQL_row *row;
 
983
                                int                     i;
 
984
 
 
985
                                row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
 
986
                                for (i = 0; i < row->nfields; i++)
 
987
                                {
 
988
                                        if (row->fieldnames[i] &&
 
989
                                                strcmp(row->fieldnames[i], cp[2]) == 0)
 
990
                                        {
 
991
                                                plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
 
992
 
 
993
                                                pfree(cp[0]);
 
994
                                                pfree(cp[1]);
 
995
                                                pfree(cp[2]);
 
996
 
 
997
                                                return T_SCALAR;
 
998
                                        }
 
999
                                }
 
1000
                                ereport(ERROR,
 
1001
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
1002
                                                 errmsg("row \"%s.%s\" has no field \"%s\"",
 
1003
                                                                cp[0], cp[1], cp[2])));
 
1004
                        }
 
1005
 
 
1006
                default:
 
1007
                        break;
 
1008
        }
 
1009
 
 
1010
        pfree(cp[0]);
 
1011
        pfree(cp[1]);
 
1012
        pfree(cp[2]);
 
1013
        return T_ERROR;
 
1014
}
 
1015
 
 
1016
 
 
1017
/* ----------
 
1018
 * plpgsql_parse_wordtype       The scanner found word%TYPE. word can be
 
1019
 *                              a variable name or a basetype.
 
1020
 * ----------
 
1021
 */
 
1022
int
 
1023
plpgsql_parse_wordtype(char *word)
 
1024
{
 
1025
        PLpgSQL_nsitem *nse;
 
1026
        bool            old_nsstate;
 
1027
        Oid                     typeOid;
 
1028
        char       *cp[2];
 
1029
        int                     i;
 
1030
 
 
1031
        /* Do case conversion and word separation */
 
1032
        /* We convert %type to .type momentarily to keep converter happy */
 
1033
        i = strlen(word) - 5;
 
1034
        Assert(word[i] == '%');
 
1035
        word[i] = '.';
 
1036
        plpgsql_convert_ident(word, cp, 2);
 
1037
        word[i] = '%';
 
1038
        pfree(cp[1]);
 
1039
 
 
1040
        /*
 
1041
         * Do a lookup on the compilers namestack. But ensure it moves up to
 
1042
         * the toplevel.
 
1043
         */
 
1044
        old_nsstate = plpgsql_ns_setlocal(false);
 
1045
        nse = plpgsql_ns_lookup(cp[0], NULL);
 
1046
        plpgsql_ns_setlocal(old_nsstate);
 
1047
 
 
1048
        if (nse != NULL)
 
1049
        {
 
1050
                pfree(cp[0]);
 
1051
                switch (nse->itemtype)
 
1052
                {
 
1053
                        case PLPGSQL_NSTYPE_VAR:
 
1054
                                plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
 
1055
                                return T_DTYPE;
 
1056
 
 
1057
                                /* XXX perhaps allow REC here? */
 
1058
 
 
1059
                        default:
 
1060
                                return T_ERROR;
 
1061
                }
 
1062
        }
 
1063
 
 
1064
        /*
 
1065
         * Word wasn't found on the namestack. Try to find a data type with
 
1066
         * that name, but ignore pg_type entries that are in fact class types.
 
1067
         */
 
1068
        typeOid = LookupTypeName(makeTypeName(cp[0]));
 
1069
        if (OidIsValid(typeOid))
 
1070
        {
 
1071
                HeapTuple       typeTup;
 
1072
 
 
1073
                typeTup = SearchSysCache(TYPEOID,
 
1074
                                                                 ObjectIdGetDatum(typeOid),
 
1075
                                                                 0, 0, 0);
 
1076
                if (HeapTupleIsValid(typeTup))
 
1077
                {
 
1078
                        Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 
1079
 
 
1080
                        if (!typeStruct->typisdefined ||
 
1081
                                typeStruct->typrelid != InvalidOid)
 
1082
                        {
 
1083
                                ReleaseSysCache(typeTup);
 
1084
                                pfree(cp[0]);
 
1085
                                return T_ERROR;
 
1086
                        }
 
1087
 
 
1088
                        plpgsql_yylval.dtype = build_datatype(typeTup, -1);
 
1089
 
 
1090
                        ReleaseSysCache(typeTup);
 
1091
                        pfree(cp[0]);
 
1092
                        return T_DTYPE;
 
1093
                }
 
1094
        }
 
1095
 
 
1096
        /*
 
1097
         * Nothing found - up to now it's a word without any special meaning
 
1098
         * for us.
 
1099
         */
 
1100
        pfree(cp[0]);
 
1101
        return T_ERROR;
 
1102
}
 
1103
 
 
1104
 
 
1105
/* ----------
 
1106
 * plpgsql_parse_dblwordtype            Same lookup for word.word%TYPE
 
1107
 * ----------
 
1108
 */
 
1109
int
 
1110
plpgsql_parse_dblwordtype(char *word)
 
1111
{
 
1112
        PLpgSQL_nsitem *nse;
 
1113
        bool            old_nsstate;
 
1114
        Oid                     classOid;
 
1115
        HeapTuple       classtup;
 
1116
        Form_pg_class classStruct;
 
1117
        HeapTuple       attrtup;
 
1118
        Form_pg_attribute attrStruct;
 
1119
        HeapTuple       typetup;
 
1120
        char       *cp[3];
 
1121
        int                     i;
 
1122
 
 
1123
        /* Do case conversion and word separation */
 
1124
        /* We convert %type to .type momentarily to keep converter happy */
 
1125
        i = strlen(word) - 5;
 
1126
        Assert(word[i] == '%');
 
1127
        word[i] = '.';
 
1128
        plpgsql_convert_ident(word, cp, 3);
 
1129
        word[i] = '%';
 
1130
        pfree(cp[2]);
 
1131
 
 
1132
        /*
 
1133
         * Lookup the first word
 
1134
         */
 
1135
        nse = plpgsql_ns_lookup(cp[0], NULL);
 
1136
 
 
1137
        /*
 
1138
         * If this is a label lookup the second word in that labels namestack
 
1139
         * level
 
1140
         */
 
1141
        if (nse != NULL)
 
1142
        {
 
1143
                if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
 
1144
                {
 
1145
                        old_nsstate = plpgsql_ns_setlocal(false);
 
1146
                        nse = plpgsql_ns_lookup(cp[1], cp[0]);
 
1147
                        plpgsql_ns_setlocal(old_nsstate);
 
1148
 
 
1149
                        pfree(cp[0]);
 
1150
                        pfree(cp[1]);
 
1151
 
 
1152
                        if (nse != NULL)
 
1153
                        {
 
1154
                                switch (nse->itemtype)
 
1155
                                {
 
1156
                                        case PLPGSQL_NSTYPE_VAR:
 
1157
                                                plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
 
1158
                                                return T_DTYPE;
 
1159
 
 
1160
                                        default:
 
1161
                                                return T_ERROR;
 
1162
                                }
 
1163
                        }
 
1164
                        return T_ERROR;
 
1165
                }
 
1166
                pfree(cp[0]);
 
1167
                pfree(cp[1]);
 
1168
                return T_ERROR;
 
1169
        }
 
1170
 
 
1171
        /*
 
1172
         * First word could also be a table name
 
1173
         */
 
1174
        classOid = RelnameGetRelid(cp[0]);
 
1175
        if (!OidIsValid(classOid))
 
1176
        {
 
1177
                pfree(cp[0]);
 
1178
                pfree(cp[1]);
 
1179
                return T_ERROR;
 
1180
        }
 
1181
        classtup = SearchSysCache(RELOID,
 
1182
                                                          ObjectIdGetDatum(classOid),
 
1183
                                                          0, 0, 0);
 
1184
        if (!HeapTupleIsValid(classtup))
 
1185
        {
 
1186
                pfree(cp[0]);
 
1187
                pfree(cp[1]);
 
1188
                return T_ERROR;
 
1189
        }
 
1190
 
 
1191
        /*
 
1192
         * It must be a relation, sequence, view, or type
 
1193
         */
 
1194
        classStruct = (Form_pg_class) GETSTRUCT(classtup);
 
1195
        if (classStruct->relkind != RELKIND_RELATION &&
 
1196
                classStruct->relkind != RELKIND_SEQUENCE &&
 
1197
                classStruct->relkind != RELKIND_VIEW &&
 
1198
                classStruct->relkind != RELKIND_COMPOSITE_TYPE)
 
1199
        {
 
1200
                ReleaseSysCache(classtup);
 
1201
                pfree(cp[0]);
 
1202
                pfree(cp[1]);
 
1203
                return T_ERROR;
 
1204
        }
 
1205
 
 
1206
        /*
 
1207
         * Fetch the named table field and it's type
 
1208
         */
 
1209
        attrtup = SearchSysCacheAttName(classOid, cp[1]);
 
1210
        if (!HeapTupleIsValid(attrtup))
 
1211
        {
 
1212
                ReleaseSysCache(classtup);
 
1213
                pfree(cp[0]);
 
1214
                pfree(cp[1]);
 
1215
                return T_ERROR;
 
1216
        }
 
1217
        attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
 
1218
 
 
1219
        typetup = SearchSysCache(TYPEOID,
 
1220
                                                         ObjectIdGetDatum(attrStruct->atttypid),
 
1221
                                                         0, 0, 0);
 
1222
        if (!HeapTupleIsValid(typetup))
 
1223
                elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
 
1224
 
 
1225
        /*
 
1226
         * Found that - build a compiler type struct and return it
 
1227
         */
 
1228
        plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
 
1229
 
 
1230
        ReleaseSysCache(classtup);
 
1231
        ReleaseSysCache(attrtup);
 
1232
        ReleaseSysCache(typetup);
 
1233
        pfree(cp[0]);
 
1234
        pfree(cp[1]);
 
1235
        return T_DTYPE;
 
1236
}
 
1237
 
 
1238
/* ----------
 
1239
 * plpgsql_parse_tripwordtype           Same lookup for word.word.word%TYPE
 
1240
 * ----------
 
1241
 */
 
1242
#define TYPE_JUNK_LEN   5
 
1243
 
 
1244
int
 
1245
plpgsql_parse_tripwordtype(char *word)
 
1246
{
 
1247
        Oid                     classOid;
 
1248
        HeapTuple       classtup;
 
1249
        Form_pg_class classStruct;
 
1250
        HeapTuple       attrtup;
 
1251
        Form_pg_attribute attrStruct;
 
1252
        HeapTuple       typetup;
 
1253
        char       *cp[2];
 
1254
        char       *colname[1];
 
1255
        int                     qualified_att_len;
 
1256
        int                     numdots = 0;
 
1257
        int                     i;
 
1258
        RangeVar   *relvar;
 
1259
 
 
1260
        /* Do case conversion and word separation */
 
1261
        qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
 
1262
        Assert(word[qualified_att_len] == '%');
 
1263
 
 
1264
        for (i = 0; i < qualified_att_len; i++)
 
1265
        {
 
1266
                if (word[i] == '.' && ++numdots == 2)
 
1267
                {
 
1268
                        cp[0] = (char *) palloc((i + 1) * sizeof(char));
 
1269
                        memset(cp[0], 0, (i + 1) * sizeof(char));
 
1270
                        memcpy(cp[0], word, i * sizeof(char));
 
1271
 
 
1272
                        /*
 
1273
                         * qualified_att_len - one based position + 1 (null
 
1274
                         * terminator)
 
1275
                         */
 
1276
                        cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
 
1277
                        memset(cp[1], 0, (qualified_att_len - i) * sizeof(char));
 
1278
                        memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
 
1279
 
 
1280
                        break;
 
1281
                }
 
1282
        }
 
1283
 
 
1284
        relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0], "plpgsql_parse_tripwordtype"));
 
1285
        classOid = RangeVarGetRelid(relvar, true);
 
1286
        if (!OidIsValid(classOid))
 
1287
        {
 
1288
                pfree(cp[0]);
 
1289
                pfree(cp[1]);
 
1290
                return T_ERROR;
 
1291
        }
 
1292
        classtup = SearchSysCache(RELOID,
 
1293
                                                          ObjectIdGetDatum(classOid),
 
1294
                                                          0, 0, 0);
 
1295
        if (!HeapTupleIsValid(classtup))
 
1296
        {
 
1297
                pfree(cp[0]);
 
1298
                pfree(cp[1]);
 
1299
                return T_ERROR;
 
1300
        }
 
1301
 
 
1302
        /*
 
1303
         * It must be a relation, sequence, view, or type
 
1304
         */
 
1305
        classStruct = (Form_pg_class) GETSTRUCT(classtup);
 
1306
        if (classStruct->relkind != RELKIND_RELATION &&
 
1307
                classStruct->relkind != RELKIND_SEQUENCE &&
 
1308
                classStruct->relkind != RELKIND_VIEW &&
 
1309
                classStruct->relkind != RELKIND_COMPOSITE_TYPE)
 
1310
        {
 
1311
                ReleaseSysCache(classtup);
 
1312
                pfree(cp[0]);
 
1313
                pfree(cp[1]);
 
1314
                return T_ERROR;
 
1315
        }
 
1316
 
 
1317
        /*
 
1318
         * Fetch the named table field and it's type
 
1319
         */
 
1320
        plpgsql_convert_ident(cp[1], colname, 1);
 
1321
        attrtup = SearchSysCacheAttName(classOid, colname[0]);
 
1322
        pfree(colname[0]);
 
1323
 
 
1324
        if (!HeapTupleIsValid(attrtup))
 
1325
        {
 
1326
                ReleaseSysCache(classtup);
 
1327
                pfree(cp[0]);
 
1328
                pfree(cp[1]);
 
1329
                return T_ERROR;
 
1330
        }
 
1331
        attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
 
1332
 
 
1333
        typetup = SearchSysCache(TYPEOID,
 
1334
                                                         ObjectIdGetDatum(attrStruct->atttypid),
 
1335
                                                         0, 0, 0);
 
1336
        if (!HeapTupleIsValid(typetup))
 
1337
                elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
 
1338
 
 
1339
        /*
 
1340
         * Found that - build a compiler type struct and return it
 
1341
         */
 
1342
        plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
 
1343
 
 
1344
        ReleaseSysCache(classtup);
 
1345
        ReleaseSysCache(attrtup);
 
1346
        ReleaseSysCache(typetup);
 
1347
        pfree(cp[0]);
 
1348
        pfree(cp[1]);
 
1349
 
 
1350
        return T_DTYPE;
 
1351
}
 
1352
 
 
1353
/* ----------
 
1354
 * plpgsql_parse_wordrowtype            Scanner found word%ROWTYPE.
 
1355
 *                                      So word must be a table name.
 
1356
 * ----------
 
1357
 */
 
1358
int
 
1359
plpgsql_parse_wordrowtype(char *word)
 
1360
{
 
1361
        Oid                     classOid;
 
1362
        char       *cp[2];
 
1363
        int                     i;
 
1364
 
 
1365
        /* Do case conversion and word separation */
 
1366
        /* We convert %rowtype to .rowtype momentarily to keep converter happy */
 
1367
        i = strlen(word) - 8;
 
1368
        Assert(word[i] == '%');
 
1369
        word[i] = '.';
 
1370
        plpgsql_convert_ident(word, cp, 2);
 
1371
        word[i] = '%';
 
1372
 
 
1373
        /* Lookup the relation */
 
1374
        classOid = RelnameGetRelid(cp[0]);
 
1375
        if (!OidIsValid(classOid))
 
1376
                ereport(ERROR,
 
1377
                                (errcode(ERRCODE_UNDEFINED_TABLE),
 
1378
                                 errmsg("relation \"%s\" does not exist", cp[0])));
 
1379
 
 
1380
        /*
 
1381
         * Build and return the row type struct
 
1382
         */
 
1383
        plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
 
1384
                                                                                                  -1);
 
1385
 
 
1386
        pfree(cp[0]);
 
1387
        pfree(cp[1]);
 
1388
 
 
1389
        return T_DTYPE;
 
1390
}
 
1391
 
 
1392
/* ----------
 
1393
 * plpgsql_parse_dblwordrowtype         Scanner found word.word%ROWTYPE.
 
1394
 *                      So word must be a namespace qualified table name.
 
1395
 * ----------
 
1396
 */
 
1397
#define ROWTYPE_JUNK_LEN        8
 
1398
 
 
1399
int
 
1400
plpgsql_parse_dblwordrowtype(char *word)
 
1401
{
 
1402
        Oid                     classOid;
 
1403
        char       *cp;
 
1404
        int                     i;
 
1405
        RangeVar   *relvar;
 
1406
 
 
1407
        /* Do case conversion and word separation */
 
1408
        /* We convert %rowtype to .rowtype momentarily to keep converter happy */
 
1409
        i = strlen(word) - ROWTYPE_JUNK_LEN;
 
1410
        Assert(word[i] == '%');
 
1411
 
 
1412
        cp = (char *) palloc((i + 1) * sizeof(char));
 
1413
        memset(cp, 0, (i + 1) * sizeof(char));
 
1414
        memcpy(cp, word, i * sizeof(char));
 
1415
 
 
1416
        /* Lookup the relation */
 
1417
        relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
 
1418
        classOid = RangeVarGetRelid(relvar, true);
 
1419
        if (!OidIsValid(classOid))
 
1420
                ereport(ERROR,
 
1421
                                (errcode(ERRCODE_UNDEFINED_TABLE),
 
1422
                                 errmsg("relation \"%s\" does not exist", cp)));
 
1423
 
 
1424
        /*
 
1425
         * Build and return the row type struct
 
1426
         */
 
1427
        plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
 
1428
                                                                                                  -1);
 
1429
 
 
1430
        pfree(cp);
 
1431
 
 
1432
        return T_DTYPE;
 
1433
}
 
1434
 
 
1435
/*
 
1436
 * plpgsql_build_variable - build a datum-array entry of a given datatype
 
1437
 *
 
1438
 * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or PLpgSQL_rec
 
1439
 * depending on the given datatype.  The struct is automatically added
 
1440
 * to the current datum array, and optionally to the current namespace.
 
1441
 */
 
1442
PLpgSQL_variable *
 
1443
plpgsql_build_variable(char *refname, int lineno, PLpgSQL_type *dtype,
 
1444
                                           bool add2namespace)
 
1445
{
 
1446
        PLpgSQL_variable *result;
 
1447
 
 
1448
        switch (dtype->ttype)
 
1449
        {
 
1450
                case PLPGSQL_TTYPE_SCALAR:
 
1451
                        {
 
1452
                                /* Ordinary scalar datatype */
 
1453
                                PLpgSQL_var *var;
 
1454
 
 
1455
                                var = malloc(sizeof(PLpgSQL_var));
 
1456
                                memset(var, 0, sizeof(PLpgSQL_var));
 
1457
 
 
1458
                                var->dtype = PLPGSQL_DTYPE_VAR;
 
1459
                                var->refname = refname;
 
1460
                                var->lineno = lineno;
 
1461
                                var->datatype = dtype;
 
1462
                                /* other fields might be filled by caller */
 
1463
 
 
1464
                                /* preset to NULL */
 
1465
                                var->value = 0;
 
1466
                                var->isnull = true;
 
1467
                                var->freeval = false;
 
1468
 
 
1469
                                plpgsql_adddatum((PLpgSQL_datum *) var);
 
1470
                                if (add2namespace)
 
1471
                                        plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
 
1472
                                                                           var->varno,
 
1473
                                                                           refname);
 
1474
                                result = (PLpgSQL_variable *) var;
 
1475
                                break;
 
1476
                        }
 
1477
                case PLPGSQL_TTYPE_ROW:
 
1478
                        {
 
1479
                                /* Composite type -- build a row variable */
 
1480
                                PLpgSQL_row *row;
 
1481
 
 
1482
                                row = build_row_var(dtype->typrelid);
 
1483
 
 
1484
                                row->dtype = PLPGSQL_DTYPE_ROW;
 
1485
                                row->refname = refname;
 
1486
                                row->lineno = lineno;
 
1487
 
 
1488
                                plpgsql_adddatum((PLpgSQL_datum *) row);
 
1489
                                if (add2namespace)
 
1490
                                        plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
 
1491
                                                                           row->rowno,
 
1492
                                                                           refname);
 
1493
                                result = (PLpgSQL_variable *) row;
 
1494
                                break;
 
1495
                        }
 
1496
                case PLPGSQL_TTYPE_REC:
 
1497
                        {
 
1498
                                /*
 
1499
                                 * "record" type -- build a variable-contents record
 
1500
                                 * variable
 
1501
                                 */
 
1502
                                PLpgSQL_rec *rec;
 
1503
 
 
1504
                                rec = malloc(sizeof(PLpgSQL_rec));
 
1505
                                memset(rec, 0, sizeof(PLpgSQL_rec));
 
1506
 
 
1507
                                rec->dtype = PLPGSQL_DTYPE_REC;
 
1508
                                rec->refname = refname;
 
1509
                                rec->lineno = lineno;
 
1510
 
 
1511
                                plpgsql_adddatum((PLpgSQL_datum *) rec);
 
1512
                                if (add2namespace)
 
1513
                                        plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
 
1514
                                                                           rec->recno,
 
1515
                                                                           refname);
 
1516
                                result = (PLpgSQL_variable *) rec;
 
1517
                                break;
 
1518
                        }
 
1519
                case PLPGSQL_TTYPE_PSEUDO:
 
1520
                        {
 
1521
                                ereport(ERROR,
 
1522
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1523
                                                 errmsg("variable \"%s\" has pseudo-type %s",
 
1524
                                                                refname, format_type_be(dtype->typoid))));
 
1525
                                result = NULL;  /* keep compiler quiet */
 
1526
                                break;
 
1527
                        }
 
1528
                default:
 
1529
                        elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
 
1530
                        result = NULL;          /* keep compiler quiet */
 
1531
                        break;
 
1532
        }
 
1533
 
 
1534
        return result;
 
1535
}
 
1536
 
 
1537
/*
 
1538
 * Build a row-variable data structure given the pg_class OID.
 
1539
 */
 
1540
static PLpgSQL_row *
 
1541
build_row_var(Oid classOid)
 
1542
{
 
1543
        PLpgSQL_row *row;
 
1544
        Relation        rel;
 
1545
        Form_pg_class classStruct;
 
1546
        const char *relname;
 
1547
        int                     i;
 
1548
        MemoryContext oldcxt;
 
1549
 
 
1550
        /*
 
1551
         * Open the relation to get info.
 
1552
         */
 
1553
        rel = relation_open(classOid, AccessShareLock);
 
1554
        classStruct = RelationGetForm(rel);
 
1555
        relname = RelationGetRelationName(rel);
 
1556
 
 
1557
        /* accept relation, sequence, view, or composite type entries */
 
1558
        if (classStruct->relkind != RELKIND_RELATION &&
 
1559
                classStruct->relkind != RELKIND_SEQUENCE &&
 
1560
                classStruct->relkind != RELKIND_VIEW &&
 
1561
                classStruct->relkind != RELKIND_COMPOSITE_TYPE)
 
1562
                ereport(ERROR,
 
1563
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
 
1564
                                 errmsg("relation \"%s\" is not a table", relname)));
 
1565
 
 
1566
        /*
 
1567
         * Create a row datum entry and all the required variables that it
 
1568
         * will point to.
 
1569
         */
 
1570
        row = malloc(sizeof(PLpgSQL_row));
 
1571
        memset(row, 0, sizeof(PLpgSQL_row));
 
1572
 
 
1573
        row->dtype = PLPGSQL_DTYPE_ROW;
 
1574
 
 
1575
        /*
 
1576
         * This is a bit ugly --- need a permanent copy of the rel's tupdesc.
 
1577
         * Someday all these mallocs should go away in favor of a per-function
 
1578
         * memory context ...
 
1579
         */
 
1580
        oldcxt = MemoryContextSwitchTo(TopMemoryContext);
 
1581
        row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
 
1582
        MemoryContextSwitchTo(oldcxt);
 
1583
 
 
1584
        row->nfields = classStruct->relnatts;
 
1585
        row->fieldnames = malloc(sizeof(char *) * row->nfields);
 
1586
        row->varnos = malloc(sizeof(int) * row->nfields);
 
1587
 
 
1588
        for (i = 0; i < row->nfields; i++)
 
1589
        {
 
1590
                Form_pg_attribute attrStruct;
 
1591
 
 
1592
                /*
 
1593
                 * Get the attribute and check for dropped column
 
1594
                 */
 
1595
                attrStruct = RelationGetDescr(rel)->attrs[i];
 
1596
 
 
1597
                if (!attrStruct->attisdropped)
 
1598
                {
 
1599
                        const char *attname;
 
1600
                        char       *refname;
 
1601
                        PLpgSQL_variable *var;
 
1602
 
 
1603
                        attname = NameStr(attrStruct->attname);
 
1604
                        refname = malloc(strlen(relname) + strlen(attname) + 2);
 
1605
                        strcpy(refname, relname);
 
1606
                        strcat(refname, ".");
 
1607
                        strcat(refname, attname);
 
1608
 
 
1609
                        /*
 
1610
                         * Create the internal variable for the field
 
1611
                         *
 
1612
                         * We know if the table definitions contain a default value or if
 
1613
                         * the field is declared in the table as NOT NULL. But it's
 
1614
                         * possible to create a table field as NOT NULL without a
 
1615
                         * default value and that would lead to problems later when
 
1616
                         * initializing the variables due to entering a block at
 
1617
                         * execution time. Thus we ignore this information for now.
 
1618
                         */
 
1619
                        var = plpgsql_build_variable(refname, 0,
 
1620
                                                         plpgsql_build_datatype(attrStruct->atttypid,
 
1621
                                                                                                  attrStruct->atttypmod),
 
1622
                                                                                 false);
 
1623
 
 
1624
                        /*
 
1625
                         * Add the variable to the row.
 
1626
                         */
 
1627
                        row->fieldnames[i] = strdup(attname);
 
1628
                        row->varnos[i] = var->dno;
 
1629
                }
 
1630
                else
 
1631
                {
 
1632
                        /* Leave a hole in the row structure for the dropped col */
 
1633
                        row->fieldnames[i] = NULL;
 
1634
                        row->varnos[i] = -1;
 
1635
                }
 
1636
        }
 
1637
 
 
1638
        relation_close(rel, AccessShareLock);
 
1639
 
 
1640
        return row;
 
1641
}
 
1642
 
 
1643
 
 
1644
/* ----------
 
1645
 * plpgsql_parse_datatype                       Scanner found something that should
 
1646
 *                                      be a datatype name.
 
1647
 * ----------
 
1648
 */
 
1649
PLpgSQL_type *
 
1650
plpgsql_parse_datatype(const char *string)
 
1651
{
 
1652
        Oid                     type_id;
 
1653
        int32           typmod;
 
1654
 
 
1655
        /* Let the main parser try to parse it under standard SQL rules */
 
1656
        parseTypeString(string, &type_id, &typmod);
 
1657
 
 
1658
        /* Okay, build a PLpgSQL_type data structure for it */
 
1659
        return plpgsql_build_datatype(type_id, typmod);
 
1660
}
 
1661
 
 
1662
/*
 
1663
 * plpgsql_build_datatype
 
1664
 *              Build PLpgSQL_type struct given type OID and typmod.
 
1665
 */
 
1666
PLpgSQL_type *
 
1667
plpgsql_build_datatype(Oid typeOid, int32 typmod)
 
1668
{
 
1669
        HeapTuple       typeTup;
 
1670
        PLpgSQL_type *typ;
 
1671
 
 
1672
        typeTup = SearchSysCache(TYPEOID,
 
1673
                                                         ObjectIdGetDatum(typeOid),
 
1674
                                                         0, 0, 0);
 
1675
        if (!HeapTupleIsValid(typeTup))
 
1676
                elog(ERROR, "cache lookup failed for type %u", typeOid);
 
1677
 
 
1678
        typ = build_datatype(typeTup, typmod);
 
1679
 
 
1680
        ReleaseSysCache(typeTup);
 
1681
 
 
1682
        return typ;
 
1683
}
 
1684
 
 
1685
/*
 
1686
 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
 
1687
 */
 
1688
static PLpgSQL_type *
 
1689
build_datatype(HeapTuple typeTup, int32 typmod)
 
1690
{
 
1691
        Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 
1692
        PLpgSQL_type *typ;
 
1693
 
 
1694
        if (!typeStruct->typisdefined)
 
1695
                ereport(ERROR,
 
1696
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1697
                                 errmsg("type \"%s\" is only a shell",
 
1698
                                                NameStr(typeStruct->typname))));
 
1699
 
 
1700
        typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
 
1701
 
 
1702
        typ->typname = strdup(NameStr(typeStruct->typname));
 
1703
        typ->typoid = HeapTupleGetOid(typeTup);
 
1704
        switch (typeStruct->typtype)
 
1705
        {
 
1706
                case 'b':                               /* base type */
 
1707
                case 'd':                               /* domain */
 
1708
                        typ->ttype = PLPGSQL_TTYPE_SCALAR;
 
1709
                        break;
 
1710
                case 'c':                               /* composite, ie, rowtype */
 
1711
                        Assert(OidIsValid(typeStruct->typrelid));
 
1712
                        typ->ttype = PLPGSQL_TTYPE_ROW;
 
1713
                        break;
 
1714
                case 'p':                               /* pseudo */
 
1715
                        if (typ->typoid == RECORDOID)
 
1716
                                typ->ttype = PLPGSQL_TTYPE_REC;
 
1717
                        else
 
1718
                                typ->ttype = PLPGSQL_TTYPE_PSEUDO;
 
1719
                        break;
 
1720
                default:
 
1721
                        elog(ERROR, "unrecognized typtype: %d",
 
1722
                                 (int) typeStruct->typtype);
 
1723
                        break;
 
1724
        }
 
1725
        typ->typlen = typeStruct->typlen;
 
1726
        typ->typbyval = typeStruct->typbyval;
 
1727
        typ->typrelid = typeStruct->typrelid;
 
1728
        typ->typioparam = getTypeIOParam(typeTup);
 
1729
        perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
 
1730
        typ->atttypmod = typmod;
 
1731
 
 
1732
        return typ;
 
1733
}
 
1734
 
 
1735
/*
 
1736
 * plpgsql_parse_err_condition
 
1737
 *              Generate PLpgSQL_condition entry(s) for an exception condition name
 
1738
 *
 
1739
 * This has to be able to return a list because there are some duplicate
 
1740
 * names in the table of error code names.
 
1741
 */
 
1742
PLpgSQL_condition *
 
1743
plpgsql_parse_err_condition(char *condname)
 
1744
{
 
1745
        int                     i;
 
1746
        PLpgSQL_condition *new;
 
1747
        PLpgSQL_condition *prev;
 
1748
 
 
1749
        /*
 
1750
         * XXX Eventually we will want to look for user-defined exception
 
1751
         * names here.
 
1752
         */
 
1753
 
 
1754
        /*
 
1755
         * OTHERS is represented as code 0 (which would map to '00000', but we
 
1756
         * have no need to represent that as an exception condition).
 
1757
         */
 
1758
        if (strcmp(condname, "others") == 0)
 
1759
        {
 
1760
                new = malloc(sizeof(PLpgSQL_condition));
 
1761
                new->sqlerrstate = 0;
 
1762
                new->condname = condname;
 
1763
                new->next = NULL;
 
1764
                return new;
 
1765
        }
 
1766
 
 
1767
        prev = NULL;
 
1768
        for (i = 0; exception_label_map[i].label != NULL; i++)
 
1769
        {
 
1770
                if (strcmp(condname, exception_label_map[i].label) == 0)
 
1771
                {
 
1772
                        new = malloc(sizeof(PLpgSQL_condition));
 
1773
                        new->sqlerrstate = exception_label_map[i].sqlerrstate;
 
1774
                        new->condname = condname;
 
1775
                        new->next = prev;
 
1776
                        prev = new;
 
1777
                }
 
1778
        }
 
1779
 
 
1780
        if (!prev)
 
1781
                ereport(ERROR,
 
1782
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1783
                                 errmsg("unrecognized exception condition \"%s\"",
 
1784
                                                condname)));
 
1785
 
 
1786
        return prev;
 
1787
}
 
1788
 
 
1789
/* ----------
 
1790
 * plpgsql_adddatum                     Add a variable, record or row
 
1791
 *                                      to the compilers datum list.
 
1792
 * ----------
 
1793
 */
 
1794
void
 
1795
plpgsql_adddatum(PLpgSQL_datum *new)
 
1796
{
 
1797
        if (plpgsql_nDatums == datums_alloc)
 
1798
        {
 
1799
                datums_alloc *= 2;
 
1800
                plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
 
1801
        }
 
1802
 
 
1803
        new->dno = plpgsql_nDatums;
 
1804
        plpgsql_Datums[plpgsql_nDatums++] = new;
 
1805
}
 
1806
 
 
1807
 
 
1808
/* ----------
 
1809
 * plpgsql_add_initdatums               Put all datum entries created
 
1810
 *                                      since the last call into the
 
1811
 *                                      finishing code block so the
 
1812
 *                                      block knows which variables to
 
1813
 *                                      reinitialize when entered.
 
1814
 * ----------
 
1815
 */
 
1816
int
 
1817
plpgsql_add_initdatums(int **varnos)
 
1818
{
 
1819
        int                     i;
 
1820
        int                     n = 0;
 
1821
 
 
1822
        for (i = datums_last; i < plpgsql_nDatums; i++)
 
1823
        {
 
1824
                switch (plpgsql_Datums[i]->dtype)
 
1825
                {
 
1826
                        case PLPGSQL_DTYPE_VAR:
 
1827
                                n++;
 
1828
                                break;
 
1829
 
 
1830
                        default:
 
1831
                                break;
 
1832
                }
 
1833
        }
 
1834
 
 
1835
        if (varnos != NULL)
 
1836
        {
 
1837
                if (n > 0)
 
1838
                {
 
1839
                        *varnos = (int *) malloc(sizeof(int) * n);
 
1840
 
 
1841
                        n = 0;
 
1842
                        for (i = datums_last; i < plpgsql_nDatums; i++)
 
1843
                        {
 
1844
                                switch (plpgsql_Datums[i]->dtype)
 
1845
                                {
 
1846
                                        case PLPGSQL_DTYPE_VAR:
 
1847
                                                (*varnos)[n++] = plpgsql_Datums[i]->dno;
 
1848
 
 
1849
                                        default:
 
1850
                                                break;
 
1851
                                }
 
1852
                        }
 
1853
                }
 
1854
                else
 
1855
                        *varnos = NULL;
 
1856
        }
 
1857
 
 
1858
        datums_last = plpgsql_nDatums;
 
1859
        return n;
 
1860
}
 
1861
 
 
1862
 
 
1863
/*
 
1864
 * Compute the hashkey for a given function invocation
 
1865
 *
 
1866
 * The hashkey is returned into the caller-provided storage at *hashkey.
 
1867
 */
 
1868
static void
 
1869
compute_function_hashkey(FunctionCallInfo fcinfo,
 
1870
                                                 Form_pg_proc procStruct,
 
1871
                                                 PLpgSQL_func_hashkey *hashkey,
 
1872
                                                 bool forValidator)
 
1873
{
 
1874
        int                     i;
 
1875
 
 
1876
        /* Make sure any unused bytes of the struct are zero */
 
1877
        MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
 
1878
 
 
1879
        /* get function OID */
 
1880
        hashkey->funcOid = fcinfo->flinfo->fn_oid;
 
1881
 
 
1882
        /*
 
1883
         * if trigger, get relation OID.  In validation mode we do not know
 
1884
         * what relation is intended to be used, so we leave trigrelOid zero;
 
1885
         * the hash entry built in this case will never really be used.
 
1886
         */
 
1887
        if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
 
1888
        {
 
1889
                TriggerData *trigdata = (TriggerData *) fcinfo->context;
 
1890
 
 
1891
                hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
 
1892
        }
 
1893
 
 
1894
        /* get the argument types */
 
1895
        for (i = 0; i < procStruct->pronargs; i++)
 
1896
        {
 
1897
                Oid                     argtypeid = procStruct->proargtypes[i];
 
1898
 
 
1899
                /*
 
1900
                 * Check for polymorphic arguments. If found, use the actual
 
1901
                 * parameter type from the caller's FuncExpr node, if we have one.
 
1902
                 * (In validation mode we arbitrarily assume we are dealing with
 
1903
                 * integers.  This lets us build a valid, if possibly useless,
 
1904
                 * function hashtable entry.)
 
1905
                 *
 
1906
                 * We can support arguments of type ANY the same way as normal
 
1907
                 * polymorphic arguments.
 
1908
                 */
 
1909
                if (argtypeid == ANYARRAYOID || argtypeid == ANYELEMENTOID ||
 
1910
                        argtypeid == ANYOID)
 
1911
                {
 
1912
                        if (forValidator)
 
1913
                        {
 
1914
                                if (argtypeid == ANYARRAYOID)
 
1915
                                        argtypeid = INT4ARRAYOID;
 
1916
                                else
 
1917
                                        argtypeid = INT4OID;
 
1918
                        }
 
1919
                        else
 
1920
                                argtypeid = get_fn_expr_argtype(fcinfo->flinfo, i);
 
1921
                        if (!OidIsValid(argtypeid))
 
1922
                                ereport(ERROR,
 
1923
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1924
                                                 errmsg("could not determine actual argument "
 
1925
                                                                "type for polymorphic function \"%s\"",
 
1926
                                                                NameStr(procStruct->proname))));
 
1927
                }
 
1928
 
 
1929
                hashkey->argtypes[i] = argtypeid;
 
1930
        }
 
1931
}
 
1932
 
 
1933
/* exported so we can call it from plpgsql_init() */
 
1934
void
 
1935
plpgsql_HashTableInit(void)
 
1936
{
 
1937
        HASHCTL         ctl;
 
1938
 
 
1939
        memset(&ctl, 0, sizeof(ctl));
 
1940
        ctl.keysize = sizeof(PLpgSQL_func_hashkey);
 
1941
        ctl.entrysize = sizeof(plpgsql_HashEnt);
 
1942
        ctl.hash = tag_hash;
 
1943
        plpgsql_HashTable = hash_create("PLpgSQL function cache",
 
1944
                                                                        FUNCS_PER_USER,
 
1945
                                                                        &ctl,
 
1946
                                                                        HASH_ELEM | HASH_FUNCTION);
 
1947
}
 
1948
 
 
1949
static PLpgSQL_function *
 
1950
plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
 
1951
{
 
1952
        plpgsql_HashEnt *hentry;
 
1953
 
 
1954
        hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
 
1955
                                                                                         (void *) func_key,
 
1956
                                                                                         HASH_FIND,
 
1957
                                                                                         NULL);
 
1958
        if (hentry)
 
1959
                return hentry->function;
 
1960
        else
 
1961
                return NULL;
 
1962
}
 
1963
 
 
1964
static void
 
1965
plpgsql_HashTableInsert(PLpgSQL_function *function,
 
1966
                                                PLpgSQL_func_hashkey *func_key)
 
1967
{
 
1968
        plpgsql_HashEnt *hentry;
 
1969
        bool            found;
 
1970
 
 
1971
        hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
 
1972
                                                                                         (void *) func_key,
 
1973
                                                                                         HASH_ENTER,
 
1974
                                                                                         &found);
 
1975
        if (hentry == NULL)
 
1976
                ereport(ERROR,
 
1977
                                (errcode(ERRCODE_OUT_OF_MEMORY),
 
1978
                                 errmsg("out of memory")));
 
1979
        if (found)
 
1980
                elog(WARNING, "trying to insert a function that already exists");
 
1981
 
 
1982
        hentry->function = function;
 
1983
        /* prepare back link from function to hashtable key */
 
1984
        function->fn_hashkey = &hentry->key;
 
1985
}
 
1986
 
 
1987
static void
 
1988
plpgsql_HashTableDelete(PLpgSQL_function *function)
 
1989
{
 
1990
        plpgsql_HashEnt *hentry;
 
1991
 
 
1992
        hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
 
1993
                                                                                   (void *) function->fn_hashkey,
 
1994
                                                                                         HASH_REMOVE,
 
1995
                                                                                         NULL);
 
1996
        if (hentry == NULL)
 
1997
                elog(WARNING, "trying to delete function that does not exist");
 
1998
}