Coverage Report

Created: 2026-09-28 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/commands/functioncmds.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * functioncmds.c
4
 *
5
 *    Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
6
 *    CAST commands.
7
 *
8
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
9
 * Portions Copyright (c) 1994, Regents of the University of California
10
 *
11
 *
12
 * IDENTIFICATION
13
 *    src/backend/commands/functioncmds.c
14
 *
15
 * DESCRIPTION
16
 *    These routines take the parse tree and pick out the
17
 *    appropriate arguments/flags, and pass the results to the
18
 *    corresponding "FooCreate" routines (in src/backend/catalog) that do
19
 *    the actual catalog-munging.  These routines also verify permission
20
 *    of the user to execute the command.
21
 *
22
 * NOTES
23
 *    These things must be defined and committed in the following order:
24
 *    "create function":
25
 *        input/output, recv/send procedures
26
 *    "create type":
27
 *        type
28
 *    "create operator":
29
 *        operators
30
 *
31
 *-------------------------------------------------------------------------
32
 */
33
#include "postgres.h"
34
35
#include "access/htup_details.h"
36
#include "access/table.h"
37
#include "access/xact.h"
38
#include "catalog/catalog.h"
39
#include "catalog/dependency.h"
40
#include "catalog/indexing.h"
41
#include "catalog/objectaccess.h"
42
#include "catalog/pg_aggregate.h"
43
#include "catalog/pg_cast.h"
44
#include "catalog/pg_language.h"
45
#include "catalog/pg_namespace.h"
46
#include "catalog/pg_proc.h"
47
#include "catalog/pg_transform.h"
48
#include "catalog/pg_type.h"
49
#include "commands/defrem.h"
50
#include "commands/extension.h"
51
#include "commands/proclang.h"
52
#include "executor/executor.h"
53
#include "executor/functions.h"
54
#include "funcapi.h"
55
#include "miscadmin.h"
56
#include "nodes/nodeFuncs.h"
57
#include "optimizer/optimizer.h"
58
#include "parser/analyze.h"
59
#include "parser/parse_coerce.h"
60
#include "parser/parse_collate.h"
61
#include "parser/parse_expr.h"
62
#include "parser/parse_func.h"
63
#include "parser/parse_type.h"
64
#include "pgstat.h"
65
#include "tcop/pquery.h"
66
#include "tcop/utility.h"
67
#include "utils/acl.h"
68
#include "utils/builtins.h"
69
#include "utils/guc.h"
70
#include "utils/lsyscache.h"
71
#include "utils/rel.h"
72
#include "utils/snapmgr.h"
73
#include "utils/syscache.h"
74
#include "utils/typcache.h"
75
76
/*
77
 *   Examine the RETURNS clause of the CREATE FUNCTION statement
78
 *   and return information about it as *prorettype_p and *returnsSet_p.
79
 *
80
 * This is more complex than the average typename lookup because we want to
81
 * allow a shell type to be used, or even created if the specified return type
82
 * doesn't exist yet.  (Without this, there's no way to define the I/O procs
83
 * for a new type.)  But SQL function creation won't cope, so error out if
84
 * the target language is SQL.  (We do this here, not in the SQL-function
85
 * validator, so as not to produce a NOTICE and then an ERROR for the same
86
 * condition.)
87
 */
88
static void
89
compute_return_type(TypeName *returnType, Oid languageOid,
90
          Oid *prorettype_p, bool *returnsSet_p)
91
0
{
92
0
  Oid     rettype;
93
0
  Type    typtup;
94
0
  AclResult aclresult;
95
0
  bool    attempt_shell_creation;
96
97
  /*
98
   * If this looks like it could be an input function, and the type doesn't
99
   * exist, we'll create it as a shell type.
100
   *
101
   * If the type name contains any modifiers like %TYPE, type[] array
102
   * syntax, or typmod decoration, it's not an input function, or at least
103
   * not one for which we'd want to automatically create a shell type.
104
   *
105
   * Only C-coded functions can be I/O functions.  We enforce this
106
   * restriction here mainly to prevent littering the catalogs with shell
107
   * types due to simple typos in user-defined function definitions.
108
   */
109
0
  attempt_shell_creation =
110
0
    !returnType->pct_type && returnType->arrayBounds == NULL &&
111
0
    returnType->typmods == NIL &&
112
0
    (languageOid == INTERNALlanguageId || languageOid == ClanguageId);
113
114
0
  typtup = LookupTypeName(NULL, returnType, NULL, false);
115
0
  if (typtup)
116
0
  {
117
    /*
118
     * Found an existing type with the given name.  Check if it's a shell
119
     * type.
120
     */
121
0
    if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
122
0
    {
123
0
      if (languageOid == SQLlanguageId)
124
0
        ereport(ERROR,
125
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
126
0
             errmsg("SQL function cannot return shell type %s",
127
0
                TypeNameToString(returnType))));
128
0
      else
129
0
        ereport(NOTICE,
130
0
            (errcode(ERRCODE_WRONG_OBJECT_TYPE),
131
0
             errmsg("return type %s is only a shell",
132
0
                TypeNameToString(returnType))));
133
0
    }
134
0
    rettype = typeTypeId(typtup);
135
0
    ReleaseSysCache(typtup);
136
0
  }
137
0
  else if (!attempt_shell_creation)
138
0
  {
139
    /* Type not found and we don't want to create a shell type */
140
0
    ereport(ERROR,
141
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
142
0
         errmsg("type \"%s\" does not exist",
143
0
            TypeNameToString(returnType))));
144
0
  }
145
0
  else
146
0
  {
147
    /* Make a shell type */
148
0
    Oid     namespaceId;
149
0
    char     *typname;
150
0
    ObjectAddress address;
151
152
0
    ereport(NOTICE,
153
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
154
0
         errmsg("type \"%s\" is not yet defined",
155
0
            TypeNameToString(returnType)),
156
0
         errdetail("Creating a shell type definition.")));
157
158
0
    namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
159
0
                            &typname);
160
0
    aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(),
161
0
                  ACL_CREATE);
162
0
    if (aclresult != ACLCHECK_OK)
163
0
      aclcheck_error(aclresult, OBJECT_SCHEMA,
164
0
               get_namespace_name(namespaceId));
165
166
0
    address = TypeShellMake(typname, namespaceId, GetUserId());
167
0
    rettype = address.objectId;
168
0
    Assert(OidIsValid(rettype));
169
    /* Ensure the new shell type is visible to ProcedureCreate */
170
0
    CommandCounterIncrement();
171
0
  }
172
173
0
  aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
174
0
  if (aclresult != ACLCHECK_OK)
175
0
    aclcheck_error_type(aclresult, rettype);
176
177
0
  *prorettype_p = rettype;
178
0
  *returnsSet_p = returnType->setof;
179
0
}
180
181
/*
182
 * Interpret the function parameter list of a CREATE FUNCTION,
183
 * CREATE PROCEDURE, or CREATE AGGREGATE statement.
184
 *
185
 * Input parameters:
186
 * parameters: list of FunctionParameter structs
187
 * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
188
 * objtype: identifies type of object being created
189
 *
190
 * Results are stored into output parameters.  parameterTypes must always
191
 * be created, but the other arrays/lists can be NULL pointers if not needed.
192
 * variadicArgType is set to the variadic array type if there's a VARIADIC
193
 * parameter (there can be only one); or to InvalidOid if not.
194
 * requiredResultType is set to InvalidOid if there are no OUT parameters,
195
 * else it is set to the OID of the implied result type.
196
 */
197
void
198
interpret_function_parameter_list(ParseState *pstate,
199
                  List *parameters,
200
                  Oid languageOid,
201
                  ObjectType objtype,
202
                  oidvector **parameterTypes,
203
                  List **parameterTypes_list,
204
                  ArrayType **allParameterTypes,
205
                  ArrayType **parameterModes,
206
                  ArrayType **parameterNames,
207
                  List **inParameterNames_list,
208
                  List **parameterDefaults,
209
                  Oid *variadicArgType,
210
                  Oid *requiredResultType)
211
0
{
212
0
  int     parameterCount = list_length(parameters);
213
0
  Oid      *inTypes;
214
0
  int     inCount = 0;
215
0
  Datum    *allTypes;
216
0
  Datum    *paramModes;
217
0
  Datum    *paramNames;
218
0
  int     outCount = 0;
219
0
  int     varCount = 0;
220
0
  bool    have_names = false;
221
0
  bool    have_defaults = false;
222
0
  ListCell   *x;
223
0
  int     i;
224
225
0
  *variadicArgType = InvalidOid; /* default result */
226
0
  *requiredResultType = InvalidOid; /* default result */
227
228
0
  inTypes = palloc_array(Oid, parameterCount);
229
0
  allTypes = palloc_array(Datum, parameterCount);
230
0
  paramModes = palloc_array(Datum, parameterCount);
231
0
  paramNames = palloc0_array(Datum, parameterCount);
232
0
  *parameterDefaults = NIL;
233
234
  /* Scan the list and extract data into work arrays */
235
0
  i = 0;
236
0
  foreach(x, parameters)
237
0
  {
238
0
    FunctionParameter *fp = (FunctionParameter *) lfirst(x);
239
0
    TypeName   *t = fp->argType;
240
0
    FunctionParameterMode fpmode = fp->mode;
241
0
    bool    isinput = false;
242
0
    Oid     toid;
243
0
    Type    typtup;
244
0
    AclResult aclresult;
245
246
    /* For our purposes here, a defaulted mode spec is identical to IN */
247
0
    if (fpmode == FUNC_PARAM_DEFAULT)
248
0
      fpmode = FUNC_PARAM_IN;
249
250
0
    typtup = LookupTypeName(pstate, t, NULL, false);
251
0
    if (typtup)
252
0
    {
253
0
      if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
254
0
      {
255
        /* As above, hard error if language is SQL */
256
0
        if (languageOid == SQLlanguageId)
257
0
          ereport(ERROR,
258
0
              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
259
0
               errmsg("SQL function cannot accept shell type %s",
260
0
                  TypeNameToString(t)),
261
0
               parser_errposition(pstate, t->location)));
262
        /* We don't allow creating aggregates on shell types either */
263
0
        else if (objtype == OBJECT_AGGREGATE)
264
0
          ereport(ERROR,
265
0
              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
266
0
               errmsg("aggregate cannot accept shell type %s",
267
0
                  TypeNameToString(t)),
268
0
               parser_errposition(pstate, t->location)));
269
0
        else
270
0
          ereport(NOTICE,
271
0
              (errcode(ERRCODE_WRONG_OBJECT_TYPE),
272
0
               errmsg("argument type %s is only a shell",
273
0
                  TypeNameToString(t)),
274
0
               parser_errposition(pstate, t->location)));
275
0
      }
276
0
      toid = typeTypeId(typtup);
277
0
      ReleaseSysCache(typtup);
278
0
    }
279
0
    else
280
0
    {
281
0
      ereport(ERROR,
282
0
          (errcode(ERRCODE_UNDEFINED_OBJECT),
283
0
           errmsg("type %s does not exist",
284
0
              TypeNameToString(t)),
285
0
           parser_errposition(pstate, t->location)));
286
0
      toid = InvalidOid; /* keep compiler quiet */
287
0
    }
288
289
0
    aclresult = object_aclcheck(TypeRelationId, toid, GetUserId(), ACL_USAGE);
290
0
    if (aclresult != ACLCHECK_OK)
291
0
      aclcheck_error_type(aclresult, toid);
292
293
0
    if (t->setof)
294
0
    {
295
0
      if (objtype == OBJECT_AGGREGATE)
296
0
        ereport(ERROR,
297
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
298
0
             errmsg("aggregates cannot accept set arguments"),
299
0
             parser_errposition(pstate, fp->location)));
300
0
      else if (objtype == OBJECT_PROCEDURE)
301
0
        ereport(ERROR,
302
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
303
0
             errmsg("procedures cannot accept set arguments"),
304
0
             parser_errposition(pstate, fp->location)));
305
0
      else
306
0
        ereport(ERROR,
307
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
308
0
             errmsg("functions cannot accept set arguments"),
309
0
             parser_errposition(pstate, fp->location)));
310
0
    }
311
312
    /* handle input parameters */
313
0
    if (fpmode != FUNC_PARAM_OUT && fpmode != FUNC_PARAM_TABLE)
314
0
    {
315
      /* other input parameters can't follow a VARIADIC parameter */
316
0
      if (varCount > 0)
317
0
        ereport(ERROR,
318
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
319
0
             errmsg("VARIADIC parameter must be the last input parameter"),
320
0
             parser_errposition(pstate, fp->location)));
321
0
      inTypes[inCount++] = toid;
322
0
      isinput = true;
323
0
      if (parameterTypes_list)
324
0
        *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
325
0
    }
326
327
    /* handle output parameters */
328
0
    if (fpmode != FUNC_PARAM_IN && fpmode != FUNC_PARAM_VARIADIC)
329
0
    {
330
0
      if (objtype == OBJECT_PROCEDURE)
331
0
      {
332
        /*
333
         * We disallow OUT-after-VARIADIC only for procedures.  While
334
         * such a case causes no confusion in ordinary function calls,
335
         * it would cause confusion in a CALL statement.
336
         */
337
0
        if (varCount > 0)
338
0
          ereport(ERROR,
339
0
              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
340
0
               errmsg("VARIADIC parameter must be the last parameter"),
341
0
               parser_errposition(pstate, fp->location)));
342
        /* Procedures with output parameters always return RECORD */
343
0
        *requiredResultType = RECORDOID;
344
0
      }
345
0
      else if (outCount == 0) /* save first output param's type */
346
0
        *requiredResultType = toid;
347
0
      outCount++;
348
0
    }
349
350
0
    if (fpmode == FUNC_PARAM_VARIADIC)
351
0
    {
352
0
      *variadicArgType = toid;
353
0
      varCount++;
354
      /* validate variadic parameter type */
355
0
      switch (toid)
356
0
      {
357
0
        case ANYARRAYOID:
358
0
        case ANYCOMPATIBLEARRAYOID:
359
0
        case ANYOID:
360
          /* okay */
361
0
          break;
362
0
        default:
363
0
          if (!OidIsValid(get_element_type(toid)))
364
0
            ereport(ERROR,
365
0
                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
366
0
                 errmsg("VARIADIC parameter must be an array"),
367
0
                 parser_errposition(pstate, fp->location)));
368
0
          break;
369
0
      }
370
0
    }
371
372
0
    allTypes[i] = ObjectIdGetDatum(toid);
373
374
0
    paramModes[i] = CharGetDatum(fpmode);
375
376
0
    if (fp->name && fp->name[0])
377
0
    {
378
0
      ListCell   *px;
379
380
      /*
381
       * As of Postgres 9.0 we disallow using the same name for two
382
       * input or two output function parameters.  Depending on the
383
       * function's language, conflicting input and output names might
384
       * be bad too, but we leave it to the PL to complain if so.
385
       */
386
0
      foreach(px, parameters)
387
0
      {
388
0
        FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
389
0
        FunctionParameterMode prevfpmode;
390
391
0
        if (prevfp == fp)
392
0
          break;
393
        /* as above, default mode is IN */
394
0
        prevfpmode = prevfp->mode;
395
0
        if (prevfpmode == FUNC_PARAM_DEFAULT)
396
0
          prevfpmode = FUNC_PARAM_IN;
397
        /* pure in doesn't conflict with pure out */
398
0
        if ((fpmode == FUNC_PARAM_IN ||
399
0
           fpmode == FUNC_PARAM_VARIADIC) &&
400
0
          (prevfpmode == FUNC_PARAM_OUT ||
401
0
           prevfpmode == FUNC_PARAM_TABLE))
402
0
          continue;
403
0
        if ((prevfpmode == FUNC_PARAM_IN ||
404
0
           prevfpmode == FUNC_PARAM_VARIADIC) &&
405
0
          (fpmode == FUNC_PARAM_OUT ||
406
0
           fpmode == FUNC_PARAM_TABLE))
407
0
          continue;
408
0
        if (prevfp->name && prevfp->name[0] &&
409
0
          strcmp(prevfp->name, fp->name) == 0)
410
0
          ereport(ERROR,
411
0
              (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
412
0
               errmsg("parameter name \"%s\" used more than once",
413
0
                  fp->name),
414
0
               parser_errposition(pstate, fp->location)));
415
0
      }
416
417
0
      paramNames[i] = CStringGetTextDatum(fp->name);
418
0
      have_names = true;
419
0
    }
420
421
0
    if (inParameterNames_list)
422
0
      *inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
423
424
0
    if (fp->defexpr)
425
0
    {
426
0
      Node     *def;
427
428
0
      if (!isinput)
429
0
        ereport(ERROR,
430
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
431
0
             errmsg("only input parameters can have default values"),
432
0
             parser_errposition(pstate, fp->location)));
433
434
0
      def = transformExpr(pstate, fp->defexpr,
435
0
                EXPR_KIND_FUNCTION_DEFAULT);
436
0
      def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
437
0
      assign_expr_collations(pstate, def);
438
439
      /*
440
       * Make sure no variables are referred to (this is probably dead
441
       * code now that add_missing_from is history).
442
       */
443
0
      if (pstate->p_rtable != NIL ||
444
0
        contain_var_clause(def))
445
0
        ereport(ERROR,
446
0
            (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
447
0
             errmsg("cannot use table references in parameter default value"),
448
0
             parser_errposition(pstate, fp->location)));
449
450
      /*
451
       * transformExpr() should have already rejected subqueries,
452
       * aggregates, and window functions, based on the EXPR_KIND_ for a
453
       * default expression.
454
       *
455
       * It can't return a set either --- but coerce_to_specific_type
456
       * already checked that for us.
457
       *
458
       * Note: the point of these restrictions is to ensure that an
459
       * expression that, on its face, hasn't got subplans, aggregates,
460
       * etc cannot suddenly have them after function default arguments
461
       * are inserted.
462
       */
463
464
0
      *parameterDefaults = lappend(*parameterDefaults, def);
465
0
      have_defaults = true;
466
0
    }
467
0
    else
468
0
    {
469
0
      if (isinput && have_defaults)
470
0
        ereport(ERROR,
471
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
472
0
             errmsg("input parameters after one with a default value must also have defaults"),
473
0
             parser_errposition(pstate, fp->location)));
474
475
      /*
476
       * For procedures, we also can't allow OUT parameters after one
477
       * with a default, because the same sort of confusion arises in a
478
       * CALL statement.
479
       */
480
0
      if (objtype == OBJECT_PROCEDURE && have_defaults)
481
0
        ereport(ERROR,
482
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
483
0
             errmsg("procedure OUT parameters cannot appear after one with a default value"),
484
0
             parser_errposition(pstate, fp->location)));
485
0
    }
486
487
0
    i++;
488
0
  }
489
490
  /* Now construct the proper outputs as needed */
491
0
  *parameterTypes = buildoidvector(inTypes, inCount);
492
493
0
  if (outCount > 0 || varCount > 0)
494
0
  {
495
0
    *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID);
496
0
    *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID);
497
0
    if (outCount > 1)
498
0
      *requiredResultType = RECORDOID;
499
    /* otherwise we set requiredResultType correctly above */
500
0
  }
501
0
  else
502
0
  {
503
0
    *allParameterTypes = NULL;
504
0
    *parameterModes = NULL;
505
0
  }
506
507
0
  if (have_names)
508
0
  {
509
0
    for (i = 0; i < parameterCount; i++)
510
0
    {
511
0
      if (paramNames[i] == PointerGetDatum(NULL))
512
0
        paramNames[i] = CStringGetTextDatum("");
513
0
    }
514
0
    *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
515
0
  }
516
0
  else
517
0
    *parameterNames = NULL;
518
0
}
519
520
521
/*
522
 * Recognize one of the options that can be passed to both CREATE
523
 * FUNCTION and ALTER FUNCTION and return it via one of the out
524
 * parameters. Returns true if the passed option was recognized. If
525
 * the out parameter we were going to assign to points to non-NULL,
526
 * raise a duplicate-clause error.  (We don't try to detect duplicate
527
 * SET parameters though --- if you're redundant, the last one wins.)
528
 */
529
static bool
530
compute_common_attribute(ParseState *pstate,
531
             bool is_procedure,
532
             DefElem *defel,
533
             DefElem **volatility_item,
534
             DefElem **strict_item,
535
             DefElem **security_item,
536
             DefElem **leakproof_item,
537
             List **set_items,
538
             DefElem **cost_item,
539
             DefElem **rows_item,
540
             DefElem **support_item,
541
             DefElem **parallel_item)
542
0
{
543
0
  if (strcmp(defel->defname, "volatility") == 0)
544
0
  {
545
0
    if (is_procedure)
546
0
      goto procedure_error;
547
0
    if (*volatility_item)
548
0
      errorConflictingDefElem(defel, pstate);
549
550
0
    *volatility_item = defel;
551
0
  }
552
0
  else if (strcmp(defel->defname, "strict") == 0)
553
0
  {
554
0
    if (is_procedure)
555
0
      goto procedure_error;
556
0
    if (*strict_item)
557
0
      errorConflictingDefElem(defel, pstate);
558
559
0
    *strict_item = defel;
560
0
  }
561
0
  else if (strcmp(defel->defname, "security") == 0)
562
0
  {
563
0
    if (*security_item)
564
0
      errorConflictingDefElem(defel, pstate);
565
566
0
    *security_item = defel;
567
0
  }
568
0
  else if (strcmp(defel->defname, "leakproof") == 0)
569
0
  {
570
0
    if (is_procedure)
571
0
      goto procedure_error;
572
0
    if (*leakproof_item)
573
0
      errorConflictingDefElem(defel, pstate);
574
575
0
    *leakproof_item = defel;
576
0
  }
577
0
  else if (strcmp(defel->defname, "set") == 0)
578
0
  {
579
0
    *set_items = lappend(*set_items, defel->arg);
580
0
  }
581
0
  else if (strcmp(defel->defname, "cost") == 0)
582
0
  {
583
0
    if (is_procedure)
584
0
      goto procedure_error;
585
0
    if (*cost_item)
586
0
      errorConflictingDefElem(defel, pstate);
587
588
0
    *cost_item = defel;
589
0
  }
590
0
  else if (strcmp(defel->defname, "rows") == 0)
591
0
  {
592
0
    if (is_procedure)
593
0
      goto procedure_error;
594
0
    if (*rows_item)
595
0
      errorConflictingDefElem(defel, pstate);
596
597
0
    *rows_item = defel;
598
0
  }
599
0
  else if (strcmp(defel->defname, "support") == 0)
600
0
  {
601
0
    if (is_procedure)
602
0
      goto procedure_error;
603
0
    if (*support_item)
604
0
      errorConflictingDefElem(defel, pstate);
605
606
0
    *support_item = defel;
607
0
  }
608
0
  else if (strcmp(defel->defname, "parallel") == 0)
609
0
  {
610
0
    if (is_procedure)
611
0
      goto procedure_error;
612
0
    if (*parallel_item)
613
0
      errorConflictingDefElem(defel, pstate);
614
615
0
    *parallel_item = defel;
616
0
  }
617
0
  else
618
0
    return false;
619
620
  /* Recognized an option */
621
0
  return true;
622
623
0
procedure_error:
624
0
  ereport(ERROR,
625
0
      (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
626
0
       errmsg("invalid attribute in procedure definition"),
627
0
       parser_errposition(pstate, defel->location)));
628
0
  return false;
629
0
}
630
631
static char
632
interpret_func_volatility(DefElem *defel)
633
0
{
634
0
  char     *str = strVal(defel->arg);
635
636
0
  if (strcmp(str, "immutable") == 0)
637
0
    return PROVOLATILE_IMMUTABLE;
638
0
  else if (strcmp(str, "stable") == 0)
639
0
    return PROVOLATILE_STABLE;
640
0
  else if (strcmp(str, "volatile") == 0)
641
0
    return PROVOLATILE_VOLATILE;
642
0
  else
643
0
  {
644
0
    elog(ERROR, "invalid volatility \"%s\"", str);
645
0
    return 0;       /* keep compiler quiet */
646
0
  }
647
0
}
648
649
static char
650
interpret_func_parallel(DefElem *defel)
651
0
{
652
0
  char     *str = strVal(defel->arg);
653
654
0
  if (strcmp(str, "safe") == 0)
655
0
    return PROPARALLEL_SAFE;
656
0
  else if (strcmp(str, "unsafe") == 0)
657
0
    return PROPARALLEL_UNSAFE;
658
0
  else if (strcmp(str, "restricted") == 0)
659
0
    return PROPARALLEL_RESTRICTED;
660
0
  else
661
0
  {
662
0
    ereport(ERROR,
663
0
        (errcode(ERRCODE_SYNTAX_ERROR),
664
0
         errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
665
0
    return PROPARALLEL_UNSAFE; /* keep compiler quiet */
666
0
  }
667
0
}
668
669
/*
670
 * Update a proconfig value according to a list of VariableSetStmt items.
671
 *
672
 * The input and result may be NULL to signify a null entry.
673
 */
674
static ArrayType *
675
update_proconfig_value(ArrayType *a, List *set_items)
676
0
{
677
0
  ListCell   *l;
678
679
0
  foreach(l, set_items)
680
0
  {
681
0
    VariableSetStmt *sstmt = lfirst_node(VariableSetStmt, l);
682
683
0
    if (sstmt->kind == VAR_RESET_ALL)
684
0
      a = NULL;
685
0
    else
686
0
    {
687
0
      char     *valuestr = ExtractSetVariableArgs(sstmt);
688
689
0
      if (valuestr)
690
0
        a = GUCArrayAdd(a, sstmt->name, valuestr);
691
0
      else        /* RESET */
692
0
        a = GUCArrayDelete(a, sstmt->name);
693
0
    }
694
0
  }
695
696
0
  return a;
697
0
}
698
699
static Oid
700
interpret_func_support(DefElem *defel)
701
0
{
702
0
  List     *procName = defGetQualifiedName(defel);
703
0
  Oid     procOid;
704
0
  Oid     argList[1];
705
706
  /*
707
   * Support functions always take one INTERNAL argument and return
708
   * INTERNAL.
709
   */
710
0
  argList[0] = INTERNALOID;
711
712
0
  procOid = LookupFuncName(procName, 1, argList, true);
713
0
  if (!OidIsValid(procOid))
714
0
    ereport(ERROR,
715
0
        (errcode(ERRCODE_UNDEFINED_FUNCTION),
716
0
         errmsg("function %s does not exist",
717
0
            func_signature_string(procName, 1, NIL, argList))));
718
719
0
  if (get_func_rettype(procOid) != INTERNALOID)
720
0
    ereport(ERROR,
721
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
722
0
         errmsg("support function %s must return type %s",
723
0
            NameListToString(procName), "internal")));
724
725
  /*
726
   * Someday we might want an ACL check here; but for now, we insist that
727
   * you be superuser to specify a support function, so privilege on the
728
   * support function is moot.
729
   */
730
0
  if (!superuser())
731
0
    ereport(ERROR,
732
0
        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
733
0
         errmsg("must be superuser to specify a support function")));
734
735
0
  return procOid;
736
0
}
737
738
739
/*
740
 * Dissect the list of options assembled in gram.y into function
741
 * attributes.
742
 */
743
static void
744
compute_function_attributes(ParseState *pstate,
745
              bool is_procedure,
746
              List *options,
747
              List **as,
748
              char **language,
749
              Node **transform,
750
              bool *windowfunc_p,
751
              char *volatility_p,
752
              bool *strict_p,
753
              bool *security_definer,
754
              bool *leakproof_p,
755
              ArrayType **proconfig,
756
              float4 *procost,
757
              float4 *prorows,
758
              Oid *prosupport,
759
              char *parallel_p)
760
0
{
761
0
  ListCell   *option;
762
0
  DefElem    *as_item = NULL;
763
0
  DefElem    *language_item = NULL;
764
0
  DefElem    *transform_item = NULL;
765
0
  DefElem    *windowfunc_item = NULL;
766
0
  DefElem    *volatility_item = NULL;
767
0
  DefElem    *strict_item = NULL;
768
0
  DefElem    *security_item = NULL;
769
0
  DefElem    *leakproof_item = NULL;
770
0
  List     *set_items = NIL;
771
0
  DefElem    *cost_item = NULL;
772
0
  DefElem    *rows_item = NULL;
773
0
  DefElem    *support_item = NULL;
774
0
  DefElem    *parallel_item = NULL;
775
776
0
  foreach(option, options)
777
0
  {
778
0
    DefElem    *defel = (DefElem *) lfirst(option);
779
780
0
    if (strcmp(defel->defname, "as") == 0)
781
0
    {
782
0
      if (as_item)
783
0
        errorConflictingDefElem(defel, pstate);
784
0
      as_item = defel;
785
0
    }
786
0
    else if (strcmp(defel->defname, "language") == 0)
787
0
    {
788
0
      if (language_item)
789
0
        errorConflictingDefElem(defel, pstate);
790
0
      language_item = defel;
791
0
    }
792
0
    else if (strcmp(defel->defname, "transform") == 0)
793
0
    {
794
0
      if (transform_item)
795
0
        errorConflictingDefElem(defel, pstate);
796
0
      transform_item = defel;
797
0
    }
798
0
    else if (strcmp(defel->defname, "window") == 0)
799
0
    {
800
0
      if (windowfunc_item)
801
0
        errorConflictingDefElem(defel, pstate);
802
0
      if (is_procedure)
803
0
        ereport(ERROR,
804
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
805
0
             errmsg("invalid attribute in procedure definition"),
806
0
             parser_errposition(pstate, defel->location)));
807
0
      windowfunc_item = defel;
808
0
    }
809
0
    else if (compute_common_attribute(pstate,
810
0
                      is_procedure,
811
0
                      defel,
812
0
                      &volatility_item,
813
0
                      &strict_item,
814
0
                      &security_item,
815
0
                      &leakproof_item,
816
0
                      &set_items,
817
0
                      &cost_item,
818
0
                      &rows_item,
819
0
                      &support_item,
820
0
                      &parallel_item))
821
0
    {
822
      /* recognized common option */
823
0
      continue;
824
0
    }
825
0
    else
826
0
      elog(ERROR, "option \"%s\" not recognized",
827
0
         defel->defname);
828
0
  }
829
830
0
  if (as_item)
831
0
    *as = (List *) as_item->arg;
832
0
  if (language_item)
833
0
    *language = strVal(language_item->arg);
834
0
  if (transform_item)
835
0
    *transform = transform_item->arg;
836
0
  if (windowfunc_item)
837
0
    *windowfunc_p = boolVal(windowfunc_item->arg);
838
0
  if (volatility_item)
839
0
    *volatility_p = interpret_func_volatility(volatility_item);
840
0
  if (strict_item)
841
0
    *strict_p = boolVal(strict_item->arg);
842
0
  if (security_item)
843
0
    *security_definer = boolVal(security_item->arg);
844
0
  if (leakproof_item)
845
0
    *leakproof_p = boolVal(leakproof_item->arg);
846
0
  if (set_items)
847
0
    *proconfig = update_proconfig_value(NULL, set_items);
848
0
  if (cost_item)
849
0
  {
850
0
    *procost = defGetNumeric(cost_item);
851
0
    if (*procost <= 0)
852
0
      ereport(ERROR,
853
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
854
0
           errmsg("COST must be positive")));
855
0
  }
856
0
  if (rows_item)
857
0
  {
858
0
    *prorows = defGetNumeric(rows_item);
859
0
    if (*prorows <= 0)
860
0
      ereport(ERROR,
861
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
862
0
           errmsg("ROWS must be positive")));
863
0
  }
864
0
  if (support_item)
865
0
    *prosupport = interpret_func_support(support_item);
866
0
  if (parallel_item)
867
0
    *parallel_p = interpret_func_parallel(parallel_item);
868
0
}
869
870
871
/*
872
 * For a dynamically linked C language object, the form of the clause is
873
 *
874
 *     AS <object file name> [, <link symbol name> ]
875
 *
876
 * In all other cases
877
 *
878
 *     AS <object reference, or sql code>
879
 */
880
static void
881
interpret_AS_clause(Oid languageOid, const char *languageName,
882
          char *funcname, List *as, Node *sql_body_in,
883
          List *parameterTypes, List *inParameterNames,
884
          char **prosrc_str_p, char **probin_str_p,
885
          Node **sql_body_out,
886
          const char *queryString)
887
0
{
888
0
  if (!sql_body_in && !as)
889
0
    ereport(ERROR,
890
0
        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
891
0
         errmsg("no function body specified")));
892
893
0
  if (sql_body_in && as)
894
0
    ereport(ERROR,
895
0
        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
896
0
         errmsg("duplicate function body specified")));
897
898
0
  if (sql_body_in && languageOid != SQLlanguageId)
899
0
    ereport(ERROR,
900
0
        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
901
0
         errmsg("inline SQL function body only valid for language SQL")));
902
903
0
  *sql_body_out = NULL;
904
905
0
  if (languageOid == ClanguageId)
906
0
  {
907
    /*
908
     * For "C" language, store the file name in probin and, when given,
909
     * the link symbol name in prosrc.  If link symbol is omitted,
910
     * substitute procedure name.  We also allow link symbol to be
911
     * specified as "-", since that was the habit in PG versions before
912
     * 8.4, and there might be dump files out there that don't translate
913
     * that back to "omitted".
914
     */
915
0
    *probin_str_p = strVal(linitial(as));
916
0
    if (list_length(as) == 1)
917
0
      *prosrc_str_p = funcname;
918
0
    else
919
0
    {
920
0
      *prosrc_str_p = strVal(lsecond(as));
921
0
      if (strcmp(*prosrc_str_p, "-") == 0)
922
0
        *prosrc_str_p = funcname;
923
0
    }
924
0
  }
925
0
  else if (sql_body_in)
926
0
  {
927
0
    SQLFunctionParseInfoPtr pinfo;
928
929
0
    pinfo = palloc0_object(SQLFunctionParseInfo);
930
931
0
    pinfo->fname = funcname;
932
0
    pinfo->nargs = list_length(parameterTypes);
933
0
    pinfo->argtypes = palloc_array(Oid, pinfo->nargs);
934
0
    pinfo->argnames = palloc_array(char *, pinfo->nargs);
935
0
    for (int i = 0; i < list_length(parameterTypes); i++)
936
0
    {
937
0
      char     *s = strVal(list_nth(inParameterNames, i));
938
939
0
      pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
940
0
      if (IsPolymorphicType(pinfo->argtypes[i]))
941
0
        ereport(ERROR,
942
0
            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
943
0
             errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
944
945
0
      if (s[0] != '\0')
946
0
        pinfo->argnames[i] = s;
947
0
      else
948
0
        pinfo->argnames[i] = NULL;
949
0
    }
950
951
0
    if (IsA(sql_body_in, List))
952
0
    {
953
0
      List     *stmts = linitial_node(List, castNode(List, sql_body_in));
954
0
      ListCell   *lc;
955
0
      List     *transformed_stmts = NIL;
956
957
0
      foreach(lc, stmts)
958
0
      {
959
0
        Node     *stmt = lfirst(lc);
960
0
        Query    *q;
961
0
        ParseState *pstate = make_parsestate(NULL);
962
963
0
        pstate->p_sourcetext = queryString;
964
0
        sql_fn_parser_setup(pstate, pinfo);
965
0
        q = transformStmt(pstate, stmt);
966
0
        if (q->commandType == CMD_UTILITY)
967
0
          ereport(ERROR,
968
0
              errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
969
0
              errmsg("%s is not yet supported in unquoted SQL function body",
970
0
                   GetCommandTagName(CreateCommandTag(q->utilityStmt))));
971
0
        transformed_stmts = lappend(transformed_stmts, q);
972
0
        free_parsestate(pstate);
973
0
      }
974
975
0
      *sql_body_out = (Node *) list_make1(transformed_stmts);
976
0
    }
977
0
    else
978
0
    {
979
0
      Query    *q;
980
0
      ParseState *pstate = make_parsestate(NULL);
981
982
0
      pstate->p_sourcetext = queryString;
983
0
      sql_fn_parser_setup(pstate, pinfo);
984
0
      q = transformStmt(pstate, sql_body_in);
985
0
      if (q->commandType == CMD_UTILITY)
986
0
        ereport(ERROR,
987
0
            errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
988
0
            errmsg("%s is not yet supported in unquoted SQL function body",
989
0
                 GetCommandTagName(CreateCommandTag(q->utilityStmt))));
990
0
      free_parsestate(pstate);
991
992
0
      *sql_body_out = (Node *) q;
993
0
    }
994
995
    /*
996
     * We must put something in prosrc.  For the moment, just record an
997
     * empty string.  It might be useful to store the original text of the
998
     * CREATE FUNCTION statement --- but to make actual use of that in
999
     * error reports, we'd also have to adjust readfuncs.c to not throw
1000
     * away node location fields when reading prosqlbody.
1001
     */
1002
0
    *prosrc_str_p = pstrdup("");
1003
1004
    /* But we definitely don't need probin. */
1005
0
    *probin_str_p = NULL;
1006
0
  }
1007
0
  else
1008
0
  {
1009
    /* Everything else wants the given string in prosrc. */
1010
0
    *prosrc_str_p = strVal(linitial(as));
1011
0
    *probin_str_p = NULL;
1012
1013
0
    if (list_length(as) != 1)
1014
0
      ereport(ERROR,
1015
0
          (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1016
0
           errmsg("only one AS item needed for language \"%s\"",
1017
0
              languageName)));
1018
1019
0
    if (languageOid == INTERNALlanguageId)
1020
0
    {
1021
      /*
1022
       * In PostgreSQL versions before 6.5, the SQL name of the created
1023
       * function could not be different from the internal name, and
1024
       * "prosrc" wasn't used.  So there is code out there that does
1025
       * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
1026
       * modicum of backwards compatibility, accept an empty "prosrc"
1027
       * value as meaning the supplied SQL function name.
1028
       */
1029
0
      if (strlen(*prosrc_str_p) == 0)
1030
0
        *prosrc_str_p = funcname;
1031
0
    }
1032
0
  }
1033
0
}
1034
1035
1036
/*
1037
 * CreateFunction
1038
 *   Execute a CREATE FUNCTION (or CREATE PROCEDURE) utility statement.
1039
 */
1040
ObjectAddress
1041
CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
1042
0
{
1043
0
  char     *probin_str;
1044
0
  char     *prosrc_str;
1045
0
  Node     *prosqlbody;
1046
0
  Oid     prorettype;
1047
0
  bool    returnsSet;
1048
0
  char     *language;
1049
0
  Oid     languageOid;
1050
0
  Oid     languageValidator;
1051
0
  Node     *transformDefElem = NULL;
1052
0
  char     *funcname;
1053
0
  Oid     namespaceId;
1054
0
  AclResult aclresult;
1055
0
  oidvector  *parameterTypes;
1056
0
  List     *parameterTypes_list = NIL;
1057
0
  ArrayType  *allParameterTypes;
1058
0
  ArrayType  *parameterModes;
1059
0
  ArrayType  *parameterNames;
1060
0
  List     *inParameterNames_list = NIL;
1061
0
  List     *parameterDefaults;
1062
0
  Oid     variadicArgType;
1063
0
  List     *trftypes_list = NIL;
1064
0
  List     *trfoids_list = NIL;
1065
0
  ArrayType  *trftypes;
1066
0
  Oid     requiredResultType;
1067
0
  bool    isWindowFunc,
1068
0
        isStrict,
1069
0
        security,
1070
0
        isLeakProof;
1071
0
  char    volatility;
1072
0
  ArrayType  *proconfig;
1073
0
  float4    procost;
1074
0
  float4    prorows;
1075
0
  Oid     prosupport;
1076
0
  HeapTuple languageTuple;
1077
0
  Form_pg_language languageStruct;
1078
0
  List     *as_clause;
1079
0
  char    parallel;
1080
1081
  /* Convert list of names to a name and namespace */
1082
0
  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1083
0
                          &funcname);
1084
1085
  /* Check we have creation rights in target namespace */
1086
0
  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
1087
0
  if (aclresult != ACLCHECK_OK)
1088
0
    aclcheck_error(aclresult, OBJECT_SCHEMA,
1089
0
             get_namespace_name(namespaceId));
1090
1091
  /* Set default attributes */
1092
0
  as_clause = NIL;
1093
0
  language = NULL;
1094
0
  isWindowFunc = false;
1095
0
  isStrict = false;
1096
0
  security = false;
1097
0
  isLeakProof = false;
1098
0
  volatility = PROVOLATILE_VOLATILE;
1099
0
  proconfig = NULL;
1100
0
  procost = -1;       /* indicates not set */
1101
0
  prorows = -1;       /* indicates not set */
1102
0
  prosupport = InvalidOid;
1103
0
  parallel = PROPARALLEL_UNSAFE;
1104
1105
  /* Extract non-default attributes from stmt->options list */
1106
0
  compute_function_attributes(pstate,
1107
0
                stmt->is_procedure,
1108
0
                stmt->options,
1109
0
                &as_clause, &language, &transformDefElem,
1110
0
                &isWindowFunc, &volatility,
1111
0
                &isStrict, &security, &isLeakProof,
1112
0
                &proconfig, &procost, &prorows,
1113
0
                &prosupport, &parallel);
1114
1115
0
  if (!language)
1116
0
  {
1117
0
    if (stmt->sql_body)
1118
0
      language = "sql";
1119
0
    else
1120
0
      ereport(ERROR,
1121
0
          (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1122
0
           errmsg("no language specified")));
1123
0
  }
1124
1125
  /* Look up the language and validate permissions */
1126
0
  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1127
0
  if (!HeapTupleIsValid(languageTuple))
1128
0
    ereport(ERROR,
1129
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
1130
0
         errmsg("language \"%s\" does not exist", language),
1131
0
         (extension_file_exists(language) ?
1132
0
          errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1133
1134
0
  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1135
0
  languageOid = languageStruct->oid;
1136
1137
0
  if (languageStruct->lanpltrusted)
1138
0
  {
1139
    /* if trusted language, need USAGE privilege */
1140
0
    aclresult = object_aclcheck(LanguageRelationId, languageOid, GetUserId(), ACL_USAGE);
1141
0
    if (aclresult != ACLCHECK_OK)
1142
0
      aclcheck_error(aclresult, OBJECT_LANGUAGE,
1143
0
               NameStr(languageStruct->lanname));
1144
0
  }
1145
0
  else
1146
0
  {
1147
    /* if untrusted language, must be superuser */
1148
0
    if (!superuser())
1149
0
      aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
1150
0
               NameStr(languageStruct->lanname));
1151
0
  }
1152
1153
0
  languageValidator = languageStruct->lanvalidator;
1154
1155
0
  ReleaseSysCache(languageTuple);
1156
1157
  /*
1158
   * Only superuser is allowed to create leakproof functions because
1159
   * leakproof functions can see tuples which have not yet been filtered out
1160
   * by security barrier views or row-level security policies.
1161
   */
1162
0
  if (isLeakProof && !superuser())
1163
0
    ereport(ERROR,
1164
0
        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1165
0
         errmsg("only superuser can define a leakproof function")));
1166
1167
0
  if (transformDefElem)
1168
0
  {
1169
0
    ListCell   *lc;
1170
1171
0
    foreach(lc, castNode(List, transformDefElem))
1172
0
    {
1173
0
      Oid     typeid = typenameTypeId(NULL,
1174
0
                        lfirst_node(TypeName, lc));
1175
0
      Oid     elt = get_base_element_type(typeid);
1176
0
      Oid     transformid;
1177
1178
0
      typeid = elt ? elt : typeid;
1179
0
      transformid = get_transform_oid(typeid, languageOid, false);
1180
0
      trftypes_list = lappend_oid(trftypes_list, typeid);
1181
0
      trfoids_list = lappend_oid(trfoids_list, transformid);
1182
0
    }
1183
0
  }
1184
1185
  /*
1186
   * Convert remaining parameters of CREATE to form wanted by
1187
   * ProcedureCreate.
1188
   */
1189
0
  interpret_function_parameter_list(pstate,
1190
0
                    stmt->parameters,
1191
0
                    languageOid,
1192
0
                    stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1193
0
                    &parameterTypes,
1194
0
                    &parameterTypes_list,
1195
0
                    &allParameterTypes,
1196
0
                    &parameterModes,
1197
0
                    &parameterNames,
1198
0
                    &inParameterNames_list,
1199
0
                    &parameterDefaults,
1200
0
                    &variadicArgType,
1201
0
                    &requiredResultType);
1202
1203
0
  if (stmt->is_procedure)
1204
0
  {
1205
0
    Assert(!stmt->returnType);
1206
0
    prorettype = requiredResultType ? requiredResultType : VOIDOID;
1207
0
    returnsSet = false;
1208
0
  }
1209
0
  else if (stmt->returnType)
1210
0
  {
1211
    /* explicit RETURNS clause */
1212
0
    compute_return_type(stmt->returnType, languageOid,
1213
0
              &prorettype, &returnsSet);
1214
0
    if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1215
0
      ereport(ERROR,
1216
0
          (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1217
0
           errmsg("function result type must be %s because of OUT parameters",
1218
0
              format_type_be(requiredResultType))));
1219
0
  }
1220
0
  else if (OidIsValid(requiredResultType))
1221
0
  {
1222
    /* default RETURNS clause from OUT parameters */
1223
0
    prorettype = requiredResultType;
1224
0
    returnsSet = false;
1225
0
  }
1226
0
  else
1227
0
  {
1228
0
    ereport(ERROR,
1229
0
        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1230
0
         errmsg("function result type must be specified")));
1231
    /* Alternative possibility: default to RETURNS VOID */
1232
0
    prorettype = VOIDOID;
1233
0
    returnsSet = false;
1234
0
  }
1235
1236
0
  if (trftypes_list != NIL)
1237
0
  {
1238
0
    ListCell   *lc;
1239
0
    Datum    *arr;
1240
0
    int     i;
1241
1242
0
    arr = palloc_array(Datum, list_length(trftypes_list));
1243
0
    i = 0;
1244
0
    foreach(lc, trftypes_list)
1245
0
      arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1246
0
    trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID);
1247
0
  }
1248
0
  else
1249
0
  {
1250
    /* store SQL NULL instead of empty array */
1251
0
    trftypes = NULL;
1252
0
  }
1253
1254
0
  interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1255
0
            parameterTypes_list, inParameterNames_list,
1256
0
            &prosrc_str, &probin_str, &prosqlbody,
1257
0
            pstate->p_sourcetext);
1258
1259
  /*
1260
   * Set default values for COST and ROWS depending on other parameters;
1261
   * reject ROWS if it's not returnsSet.  NB: pg_dump knows these default
1262
   * values, keep it in sync if you change them.
1263
   */
1264
0
  if (procost < 0)
1265
0
  {
1266
    /* SQL and PL-language functions are assumed more expensive */
1267
0
    if (languageOid == INTERNALlanguageId ||
1268
0
      languageOid == ClanguageId)
1269
0
      procost = 1;
1270
0
    else
1271
0
      procost = 100;
1272
0
  }
1273
0
  if (prorows < 0)
1274
0
  {
1275
0
    if (returnsSet)
1276
0
      prorows = 1000;
1277
0
    else
1278
0
      prorows = 0;   /* dummy value if not returnsSet */
1279
0
  }
1280
0
  else if (!returnsSet)
1281
0
    ereport(ERROR,
1282
0
        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1283
0
         errmsg("ROWS is not applicable when function does not return a set")));
1284
1285
  /*
1286
   * And now that we have all the parameters, and know we're permitted to do
1287
   * so, go ahead and create the function.
1288
   */
1289
0
  return ProcedureCreate(funcname,
1290
0
               namespaceId,
1291
0
               stmt->replace,
1292
0
               returnsSet,
1293
0
               prorettype,
1294
0
               GetUserId(),
1295
0
               languageOid,
1296
0
               languageValidator,
1297
0
               prosrc_str,  /* converted to text later */
1298
0
               probin_str,  /* converted to text later */
1299
0
               prosqlbody,
1300
0
               stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1301
0
               security,
1302
0
               isLeakProof,
1303
0
               isStrict,
1304
0
               volatility,
1305
0
               parallel,
1306
0
               parameterTypes,
1307
0
               PointerGetDatum(allParameterTypes),
1308
0
               PointerGetDatum(parameterModes),
1309
0
               PointerGetDatum(parameterNames),
1310
0
               parameterDefaults,
1311
0
               PointerGetDatum(trftypes),
1312
0
               trfoids_list,
1313
0
               PointerGetDatum(proconfig),
1314
0
               prosupport,
1315
0
               procost,
1316
0
               prorows);
1317
0
}
1318
1319
/*
1320
 * Guts of function deletion.
1321
 *
1322
 * Note: this is also used for aggregate deletion, since the OIDs of
1323
 * both functions and aggregates point to pg_proc.
1324
 */
1325
void
1326
RemoveFunctionById(Oid funcOid)
1327
0
{
1328
0
  Relation  relation;
1329
0
  HeapTuple tup;
1330
0
  char    prokind;
1331
1332
  /*
1333
   * Delete the pg_proc tuple.
1334
   */
1335
0
  relation = table_open(ProcedureRelationId, RowExclusiveLock);
1336
1337
0
  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1338
0
  if (!HeapTupleIsValid(tup)) /* should not happen */
1339
0
    elog(ERROR, "cache lookup failed for function %u", funcOid);
1340
1341
0
  prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1342
1343
0
  CatalogTupleDelete(relation, &tup->t_self);
1344
1345
0
  ReleaseSysCache(tup);
1346
1347
0
  table_close(relation, RowExclusiveLock);
1348
1349
0
  pgstat_drop_function(funcOid);
1350
1351
  /*
1352
   * If there's a pg_aggregate tuple, delete that too.
1353
   */
1354
0
  if (prokind == PROKIND_AGGREGATE)
1355
0
  {
1356
0
    relation = table_open(AggregateRelationId, RowExclusiveLock);
1357
1358
0
    tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1359
0
    if (!HeapTupleIsValid(tup)) /* should not happen */
1360
0
      elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1361
1362
0
    CatalogTupleDelete(relation, &tup->t_self);
1363
1364
0
    ReleaseSysCache(tup);
1365
1366
0
    table_close(relation, RowExclusiveLock);
1367
0
  }
1368
0
}
1369
1370
/*
1371
 * Implements the ALTER FUNCTION utility command (except for the
1372
 * RENAME and OWNER clauses, which are handled as part of the generic
1373
 * ALTER framework).
1374
 */
1375
ObjectAddress
1376
AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
1377
0
{
1378
0
  HeapTuple tup;
1379
0
  Oid     funcOid;
1380
0
  Form_pg_proc procForm;
1381
0
  bool    is_procedure;
1382
0
  Relation  rel;
1383
0
  ListCell   *l;
1384
0
  DefElem    *volatility_item = NULL;
1385
0
  DefElem    *strict_item = NULL;
1386
0
  DefElem    *security_def_item = NULL;
1387
0
  DefElem    *leakproof_item = NULL;
1388
0
  List     *set_items = NIL;
1389
0
  DefElem    *cost_item = NULL;
1390
0
  DefElem    *rows_item = NULL;
1391
0
  DefElem    *support_item = NULL;
1392
0
  DefElem    *parallel_item = NULL;
1393
0
  ObjectAddress address;
1394
1395
0
  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1396
1397
0
  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1398
1399
0
  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1400
1401
0
  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1402
0
  if (!HeapTupleIsValid(tup)) /* should not happen */
1403
0
    elog(ERROR, "cache lookup failed for function %u", funcOid);
1404
1405
0
  procForm = (Form_pg_proc) GETSTRUCT(tup);
1406
1407
  /* Permission check: must own function */
1408
0
  if (!object_ownercheck(ProcedureRelationId, funcOid, GetUserId()))
1409
0
    aclcheck_error(ACLCHECK_NOT_OWNER, stmt->objtype,
1410
0
             NameListToString(stmt->func->objname));
1411
1412
0
  if (procForm->prokind == PROKIND_AGGREGATE)
1413
0
    ereport(ERROR,
1414
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1415
0
         errmsg("\"%s\" is an aggregate function",
1416
0
            NameListToString(stmt->func->objname))));
1417
1418
0
  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1419
1420
  /* Examine requested actions. */
1421
0
  foreach(l, stmt->actions)
1422
0
  {
1423
0
    DefElem    *defel = (DefElem *) lfirst(l);
1424
1425
0
    if (compute_common_attribute(pstate,
1426
0
                   is_procedure,
1427
0
                   defel,
1428
0
                   &volatility_item,
1429
0
                   &strict_item,
1430
0
                   &security_def_item,
1431
0
                   &leakproof_item,
1432
0
                   &set_items,
1433
0
                   &cost_item,
1434
0
                   &rows_item,
1435
0
                   &support_item,
1436
0
                   &parallel_item) == false)
1437
0
      elog(ERROR, "option \"%s\" not recognized", defel->defname);
1438
0
  }
1439
1440
0
  if (volatility_item)
1441
0
    procForm->provolatile = interpret_func_volatility(volatility_item);
1442
0
  if (strict_item)
1443
0
    procForm->proisstrict = boolVal(strict_item->arg);
1444
0
  if (security_def_item)
1445
0
    procForm->prosecdef = boolVal(security_def_item->arg);
1446
0
  if (leakproof_item)
1447
0
  {
1448
0
    procForm->proleakproof = boolVal(leakproof_item->arg);
1449
0
    if (procForm->proleakproof && !superuser())
1450
0
      ereport(ERROR,
1451
0
          (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1452
0
           errmsg("only superuser can define a leakproof function")));
1453
0
  }
1454
0
  if (cost_item)
1455
0
  {
1456
0
    procForm->procost = defGetNumeric(cost_item);
1457
0
    if (procForm->procost <= 0)
1458
0
      ereport(ERROR,
1459
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1460
0
           errmsg("COST must be positive")));
1461
0
  }
1462
0
  if (rows_item)
1463
0
  {
1464
0
    procForm->prorows = defGetNumeric(rows_item);
1465
0
    if (procForm->prorows <= 0)
1466
0
      ereport(ERROR,
1467
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1468
0
           errmsg("ROWS must be positive")));
1469
0
    if (!procForm->proretset)
1470
0
      ereport(ERROR,
1471
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1472
0
           errmsg("ROWS is not applicable when function does not return a set")));
1473
0
  }
1474
0
  if (support_item)
1475
0
  {
1476
    /* interpret_func_support handles the privilege check */
1477
0
    Oid     newsupport = interpret_func_support(support_item);
1478
1479
    /* Add or replace dependency on support function */
1480
0
    if (OidIsValid(procForm->prosupport))
1481
0
    {
1482
0
      if (changeDependencyFor(ProcedureRelationId, funcOid,
1483
0
                  ProcedureRelationId, procForm->prosupport,
1484
0
                  newsupport) != 1)
1485
0
        elog(ERROR, "could not change support dependency for function %s",
1486
0
           get_func_name(funcOid));
1487
0
    }
1488
0
    else
1489
0
    {
1490
0
      ObjectAddress referenced;
1491
1492
0
      referenced.classId = ProcedureRelationId;
1493
0
      referenced.objectId = newsupport;
1494
0
      referenced.objectSubId = 0;
1495
0
      recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1496
0
    }
1497
1498
0
    procForm->prosupport = newsupport;
1499
0
  }
1500
0
  if (parallel_item)
1501
0
    procForm->proparallel = interpret_func_parallel(parallel_item);
1502
0
  if (set_items)
1503
0
  {
1504
0
    Datum   datum;
1505
0
    bool    isnull;
1506
0
    ArrayType  *a;
1507
0
    Datum   repl_val[Natts_pg_proc];
1508
0
    bool    repl_null[Natts_pg_proc];
1509
0
    bool    repl_repl[Natts_pg_proc];
1510
1511
    /* extract existing proconfig setting */
1512
0
    datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1513
0
    a = isnull ? NULL : DatumGetArrayTypeP(datum);
1514
1515
    /* update according to each SET or RESET item, left to right */
1516
0
    a = update_proconfig_value(a, set_items);
1517
1518
    /* update the tuple */
1519
0
    memset(repl_repl, false, sizeof(repl_repl));
1520
0
    repl_repl[Anum_pg_proc_proconfig - 1] = true;
1521
1522
0
    if (a == NULL)
1523
0
    {
1524
0
      repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1525
0
      repl_null[Anum_pg_proc_proconfig - 1] = true;
1526
0
    }
1527
0
    else
1528
0
    {
1529
0
      repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1530
0
      repl_null[Anum_pg_proc_proconfig - 1] = false;
1531
0
    }
1532
1533
0
    tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1534
0
                repl_val, repl_null, repl_repl);
1535
0
  }
1536
  /* DO NOT put more touches of procForm below here; it's now dangling. */
1537
1538
  /* Do the update */
1539
0
  CatalogTupleUpdate(rel, &tup->t_self, tup);
1540
1541
0
  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1542
1543
0
  table_close(rel, NoLock);
1544
0
  heap_freetuple(tup);
1545
1546
0
  return address;
1547
0
}
1548
1549
1550
/*
1551
 * CREATE CAST
1552
 */
1553
ObjectAddress
1554
CreateCast(CreateCastStmt *stmt)
1555
0
{
1556
0
  Oid     sourcetypeid;
1557
0
  Oid     targettypeid;
1558
0
  char    sourcetyptype;
1559
0
  char    targettyptype;
1560
0
  Oid     funcid;
1561
0
  Oid     incastid = InvalidOid;
1562
0
  Oid     outcastid = InvalidOid;
1563
0
  int     nargs;
1564
0
  char    castcontext;
1565
0
  char    castmethod;
1566
0
  HeapTuple tuple;
1567
0
  AclResult aclresult;
1568
0
  ObjectAddress myself;
1569
1570
0
  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1571
0
  targettypeid = typenameTypeId(NULL, stmt->targettype);
1572
0
  sourcetyptype = get_typtype(sourcetypeid);
1573
0
  targettyptype = get_typtype(targettypeid);
1574
1575
  /* No pseudo-types allowed */
1576
0
  if (sourcetyptype == TYPTYPE_PSEUDO)
1577
0
    ereport(ERROR,
1578
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1579
0
         errmsg("source data type %s is a pseudo-type",
1580
0
            TypeNameToString(stmt->sourcetype))));
1581
1582
0
  if (targettyptype == TYPTYPE_PSEUDO)
1583
0
    ereport(ERROR,
1584
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1585
0
         errmsg("target data type %s is a pseudo-type",
1586
0
            TypeNameToString(stmt->targettype))));
1587
1588
  /* Permission check */
1589
0
  if (!object_ownercheck(TypeRelationId, sourcetypeid, GetUserId())
1590
0
    && !object_ownercheck(TypeRelationId, targettypeid, GetUserId()))
1591
0
    ereport(ERROR,
1592
0
        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1593
0
         errmsg("must be owner of type %s or type %s",
1594
0
            format_type_be(sourcetypeid),
1595
0
            format_type_be(targettypeid))));
1596
1597
0
  aclresult = object_aclcheck(TypeRelationId, sourcetypeid, GetUserId(), ACL_USAGE);
1598
0
  if (aclresult != ACLCHECK_OK)
1599
0
    aclcheck_error_type(aclresult, sourcetypeid);
1600
1601
0
  aclresult = object_aclcheck(TypeRelationId, targettypeid, GetUserId(), ACL_USAGE);
1602
0
  if (aclresult != ACLCHECK_OK)
1603
0
    aclcheck_error_type(aclresult, targettypeid);
1604
1605
  /* Domains are allowed for historical reasons, but we warn */
1606
0
  if (sourcetyptype == TYPTYPE_DOMAIN)
1607
0
    ereport(WARNING,
1608
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1609
0
         errmsg("cast will be ignored because the source data type is a domain")));
1610
1611
0
  else if (targettyptype == TYPTYPE_DOMAIN)
1612
0
    ereport(WARNING,
1613
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1614
0
         errmsg("cast will be ignored because the target data type is a domain")));
1615
1616
  /* Determine the cast method */
1617
0
  if (stmt->func != NULL)
1618
0
    castmethod = COERCION_METHOD_FUNCTION;
1619
0
  else if (stmt->inout)
1620
0
    castmethod = COERCION_METHOD_INOUT;
1621
0
  else
1622
0
    castmethod = COERCION_METHOD_BINARY;
1623
1624
0
  if (castmethod == COERCION_METHOD_FUNCTION)
1625
0
  {
1626
0
    Form_pg_proc procstruct;
1627
1628
0
    funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1629
1630
0
    tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1631
0
    if (!HeapTupleIsValid(tuple))
1632
0
      elog(ERROR, "cache lookup failed for function %u", funcid);
1633
1634
0
    procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1635
0
    nargs = procstruct->pronargs;
1636
0
    if (nargs < 1 || nargs > 3)
1637
0
      ereport(ERROR,
1638
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1639
0
           errmsg("cast function must take one to three arguments")));
1640
0
    if (!IsBinaryCoercibleWithCast(sourcetypeid,
1641
0
                     procstruct->proargtypes.values[0],
1642
0
                     &incastid))
1643
0
      ereport(ERROR,
1644
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1645
0
           errmsg("argument of cast function must match or be binary-coercible from source data type")));
1646
0
    if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1647
0
      ereport(ERROR,
1648
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1649
0
           errmsg("second argument of cast function must be type %s",
1650
0
              "integer")));
1651
0
    if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1652
0
      ereport(ERROR,
1653
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1654
0
           errmsg("third argument of cast function must be type %s",
1655
0
              "boolean")));
1656
0
    if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1657
0
                     targettypeid,
1658
0
                     &outcastid))
1659
0
      ereport(ERROR,
1660
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1661
0
           errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1662
1663
    /*
1664
     * Restricting the volatility of a cast function may or may not be a
1665
     * good idea in the abstract, but it definitely breaks many old
1666
     * user-defined types.  Disable this check --- tgl 2/1/03
1667
     */
1668
#ifdef NOT_USED
1669
    if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1670
      ereport(ERROR,
1671
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1672
           errmsg("cast function must not be volatile")));
1673
#endif
1674
0
    if (procstruct->prokind != PROKIND_FUNCTION)
1675
0
      ereport(ERROR,
1676
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1677
0
           errmsg("cast function must be a normal function")));
1678
0
    if (procstruct->proretset)
1679
0
      ereport(ERROR,
1680
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1681
0
           errmsg("cast function must not return a set")));
1682
1683
0
    ReleaseSysCache(tuple);
1684
0
  }
1685
0
  else
1686
0
  {
1687
0
    funcid = InvalidOid;
1688
0
    nargs = 0;
1689
0
  }
1690
1691
0
  if (castmethod == COERCION_METHOD_BINARY)
1692
0
  {
1693
0
    int16   typ1len;
1694
0
    int16   typ2len;
1695
0
    bool    typ1byval;
1696
0
    bool    typ2byval;
1697
0
    char    typ1align;
1698
0
    char    typ2align;
1699
1700
    /*
1701
     * Must be superuser to create binary-compatible casts, since
1702
     * erroneous casts can easily crash the backend.
1703
     */
1704
0
    if (!superuser())
1705
0
      ereport(ERROR,
1706
0
          (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1707
0
           errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1708
1709
    /*
1710
     * Also, insist that the types match as to size, alignment, and
1711
     * pass-by-value attributes; this provides at least a crude check that
1712
     * they have similar representations.  A pair of types that fail this
1713
     * test should certainly not be equated.
1714
     */
1715
0
    get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1716
0
    get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1717
0
    if (typ1len != typ2len ||
1718
0
      typ1byval != typ2byval ||
1719
0
      typ1align != typ2align)
1720
0
      ereport(ERROR,
1721
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1722
0
           errmsg("source and target data types are not physically compatible")));
1723
1724
    /*
1725
     * We know that composite, array, range and enum types are never
1726
     * binary-compatible with each other.  They all have OIDs embedded in
1727
     * them.
1728
     *
1729
     * Theoretically you could build a user-defined base type that is
1730
     * binary-compatible with such a type.  But we disallow it anyway, as
1731
     * in practice such a cast is surely a mistake.  You can always work
1732
     * around that by writing a cast function.
1733
     *
1734
     * NOTE: if we ever have a kind of container type that doesn't need to
1735
     * be rejected for this reason, we'd likely need to recursively apply
1736
     * all of these same checks to the contained type(s).
1737
     */
1738
0
    if (sourcetyptype == TYPTYPE_COMPOSITE ||
1739
0
      targettyptype == TYPTYPE_COMPOSITE)
1740
0
      ereport(ERROR,
1741
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1742
0
           errmsg("composite data types are not binary-compatible")));
1743
1744
0
    if (OidIsValid(get_element_type(sourcetypeid)) ||
1745
0
      OidIsValid(get_element_type(targettypeid)))
1746
0
      ereport(ERROR,
1747
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1748
0
           errmsg("array data types are not binary-compatible")));
1749
1750
0
    if (sourcetyptype == TYPTYPE_RANGE ||
1751
0
      targettyptype == TYPTYPE_RANGE ||
1752
0
      sourcetyptype == TYPTYPE_MULTIRANGE ||
1753
0
      targettyptype == TYPTYPE_MULTIRANGE)
1754
0
      ereport(ERROR,
1755
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1756
0
           errmsg("range data types are not binary-compatible")));
1757
1758
0
    if (sourcetyptype == TYPTYPE_ENUM ||
1759
0
      targettyptype == TYPTYPE_ENUM)
1760
0
      ereport(ERROR,
1761
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1762
0
           errmsg("enum data types are not binary-compatible")));
1763
1764
    /*
1765
     * We also disallow creating binary-compatibility casts involving
1766
     * domains.  Casting from a domain to its base type is already
1767
     * allowed, and casting the other way ought to go through domain
1768
     * coercion to permit constraint checking.  Again, if you're intent on
1769
     * having your own semantics for that, create a no-op cast function.
1770
     *
1771
     * NOTE: if we were to relax this, the above checks for composites
1772
     * etc. would have to be modified to look through domains to their
1773
     * base types.
1774
     */
1775
0
    if (sourcetyptype == TYPTYPE_DOMAIN ||
1776
0
      targettyptype == TYPTYPE_DOMAIN)
1777
0
      ereport(ERROR,
1778
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1779
0
           errmsg("domain data types must not be marked binary-compatible")));
1780
0
  }
1781
1782
  /*
1783
   * Allow source and target types to be same only for length coercion
1784
   * functions.  We assume a multi-arg function does length coercion.
1785
   */
1786
0
  if (sourcetypeid == targettypeid && nargs < 2)
1787
0
    ereport(ERROR,
1788
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1789
0
         errmsg("source data type and target data type are the same")));
1790
1791
  /* convert CoercionContext enum to char value for castcontext */
1792
0
  switch (stmt->context)
1793
0
  {
1794
0
    case COERCION_IMPLICIT:
1795
0
      castcontext = COERCION_CODE_IMPLICIT;
1796
0
      break;
1797
0
    case COERCION_ASSIGNMENT:
1798
0
      castcontext = COERCION_CODE_ASSIGNMENT;
1799
0
      break;
1800
      /* COERCION_PLPGSQL is intentionally not covered here */
1801
0
    case COERCION_EXPLICIT:
1802
0
      castcontext = COERCION_CODE_EXPLICIT;
1803
0
      break;
1804
0
    default:
1805
0
      elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1806
0
      castcontext = 0;  /* keep compiler quiet */
1807
0
      break;
1808
0
  }
1809
1810
0
  myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1811
0
            castcontext, castmethod, DEPENDENCY_NORMAL);
1812
0
  return myself;
1813
0
}
1814
1815
1816
static void
1817
check_transform_function(Form_pg_proc procstruct)
1818
0
{
1819
0
  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1820
0
    ereport(ERROR,
1821
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1822
0
         errmsg("transform function must not be volatile")));
1823
0
  if (procstruct->prokind != PROKIND_FUNCTION)
1824
0
    ereport(ERROR,
1825
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1826
0
         errmsg("transform function must be a normal function")));
1827
0
  if (procstruct->proretset)
1828
0
    ereport(ERROR,
1829
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1830
0
         errmsg("transform function must not return a set")));
1831
0
  if (procstruct->pronargs != 1)
1832
0
    ereport(ERROR,
1833
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1834
0
         errmsg("transform function must take one argument")));
1835
0
  if (procstruct->proargtypes.values[0] != INTERNALOID)
1836
0
    ereport(ERROR,
1837
0
        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1838
0
         errmsg("first argument of transform function must be type %s",
1839
0
            "internal")));
1840
0
}
1841
1842
1843
/*
1844
 * CREATE TRANSFORM
1845
 */
1846
ObjectAddress
1847
CreateTransform(CreateTransformStmt *stmt)
1848
0
{
1849
0
  Oid     typeid;
1850
0
  char    typtype;
1851
0
  Oid     langid;
1852
0
  Oid     fromsqlfuncid;
1853
0
  Oid     tosqlfuncid;
1854
0
  AclResult aclresult;
1855
0
  Form_pg_proc procstruct;
1856
0
  Datum   values[Natts_pg_transform];
1857
0
  bool    nulls[Natts_pg_transform] = {0};
1858
0
  bool    replaces[Natts_pg_transform] = {0};
1859
0
  Oid     transformid;
1860
0
  HeapTuple tuple;
1861
0
  HeapTuple newtuple;
1862
0
  Relation  relation;
1863
0
  ObjectAddress myself,
1864
0
        referenced;
1865
0
  ObjectAddresses *addrs;
1866
0
  bool    is_replace;
1867
1868
  /*
1869
   * Get the type
1870
   */
1871
0
  typeid = typenameTypeId(NULL, stmt->type_name);
1872
0
  typtype = get_typtype(typeid);
1873
1874
0
  if (typtype == TYPTYPE_PSEUDO)
1875
0
    ereport(ERROR,
1876
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1877
0
         errmsg("data type %s is a pseudo-type",
1878
0
            TypeNameToString(stmt->type_name))));
1879
1880
0
  if (typtype == TYPTYPE_DOMAIN)
1881
0
    ereport(ERROR,
1882
0
        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1883
0
         errmsg("data type %s is a domain",
1884
0
            TypeNameToString(stmt->type_name))));
1885
1886
0
  if (!object_ownercheck(TypeRelationId, typeid, GetUserId()))
1887
0
    aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid);
1888
1889
0
  aclresult = object_aclcheck(TypeRelationId, typeid, GetUserId(), ACL_USAGE);
1890
0
  if (aclresult != ACLCHECK_OK)
1891
0
    aclcheck_error_type(aclresult, typeid);
1892
1893
  /*
1894
   * Get the language
1895
   */
1896
0
  langid = get_language_oid(stmt->lang, false);
1897
1898
0
  aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), ACL_USAGE);
1899
0
  if (aclresult != ACLCHECK_OK)
1900
0
    aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1901
1902
  /*
1903
   * Get the functions
1904
   */
1905
0
  if (stmt->fromsql)
1906
0
  {
1907
0
    fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1908
1909
0
    if (!object_ownercheck(ProcedureRelationId, fromsqlfuncid, GetUserId()))
1910
0
      aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1911
1912
0
    aclresult = object_aclcheck(ProcedureRelationId, fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1913
0
    if (aclresult != ACLCHECK_OK)
1914
0
      aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1915
1916
0
    tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1917
0
    if (!HeapTupleIsValid(tuple))
1918
0
      elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1919
0
    procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1920
0
    if (procstruct->prorettype != INTERNALOID)
1921
0
      ereport(ERROR,
1922
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1923
0
           errmsg("return data type of FROM SQL function must be %s",
1924
0
              "internal")));
1925
0
    check_transform_function(procstruct);
1926
0
    ReleaseSysCache(tuple);
1927
0
  }
1928
0
  else
1929
0
    fromsqlfuncid = InvalidOid;
1930
1931
0
  if (stmt->tosql)
1932
0
  {
1933
0
    tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1934
1935
0
    if (!object_ownercheck(ProcedureRelationId, tosqlfuncid, GetUserId()))
1936
0
      aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1937
1938
0
    aclresult = object_aclcheck(ProcedureRelationId, tosqlfuncid, GetUserId(), ACL_EXECUTE);
1939
0
    if (aclresult != ACLCHECK_OK)
1940
0
      aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1941
1942
0
    tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1943
0
    if (!HeapTupleIsValid(tuple))
1944
0
      elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1945
0
    procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1946
0
    if (procstruct->prorettype != typeid)
1947
0
      ereport(ERROR,
1948
0
          (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1949
0
           errmsg("return data type of TO SQL function must be the transform data type")));
1950
0
    check_transform_function(procstruct);
1951
0
    ReleaseSysCache(tuple);
1952
0
  }
1953
0
  else
1954
0
    tosqlfuncid = InvalidOid;
1955
1956
  /*
1957
   * Ready to go
1958
   */
1959
0
  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1960
0
  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1961
0
  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1962
0
  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1963
1964
0
  relation = table_open(TransformRelationId, RowExclusiveLock);
1965
1966
0
  tuple = SearchSysCache2(TRFTYPELANG,
1967
0
              ObjectIdGetDatum(typeid),
1968
0
              ObjectIdGetDatum(langid));
1969
0
  if (HeapTupleIsValid(tuple))
1970
0
  {
1971
0
    Form_pg_transform form = (Form_pg_transform) GETSTRUCT(tuple);
1972
1973
0
    if (!stmt->replace)
1974
0
      ereport(ERROR,
1975
0
          (errcode(ERRCODE_DUPLICATE_OBJECT),
1976
0
           errmsg("transform for type %s language \"%s\" already exists",
1977
0
              format_type_be(typeid),
1978
0
              stmt->lang)));
1979
1980
0
    replaces[Anum_pg_transform_trffromsql - 1] = true;
1981
0
    replaces[Anum_pg_transform_trftosql - 1] = true;
1982
1983
0
    newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1984
0
    CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1985
1986
0
    transformid = form->oid;
1987
0
    ReleaseSysCache(tuple);
1988
0
    is_replace = true;
1989
0
  }
1990
0
  else
1991
0
  {
1992
0
    transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1993
0
                     Anum_pg_transform_oid);
1994
0
    values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1995
0
    newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1996
0
    CatalogTupleInsert(relation, newtuple);
1997
0
    is_replace = false;
1998
0
  }
1999
2000
0
  if (is_replace)
2001
0
    deleteDependencyRecordsFor(TransformRelationId, transformid, true);
2002
2003
0
  addrs = new_object_addresses();
2004
2005
  /* make dependency entries */
2006
0
  ObjectAddressSet(myself, TransformRelationId, transformid);
2007
2008
  /* dependency on language */
2009
0
  ObjectAddressSet(referenced, LanguageRelationId, langid);
2010
0
  add_exact_object_address(&referenced, addrs);
2011
2012
  /* dependency on type */
2013
0
  ObjectAddressSet(referenced, TypeRelationId, typeid);
2014
0
  add_exact_object_address(&referenced, addrs);
2015
2016
  /* dependencies on functions */
2017
0
  if (OidIsValid(fromsqlfuncid))
2018
0
  {
2019
0
    ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
2020
0
    add_exact_object_address(&referenced, addrs);
2021
0
  }
2022
0
  if (OidIsValid(tosqlfuncid))
2023
0
  {
2024
0
    ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
2025
0
    add_exact_object_address(&referenced, addrs);
2026
0
  }
2027
2028
0
  record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
2029
0
  free_object_addresses(addrs);
2030
2031
  /* dependency on extension */
2032
0
  recordDependencyOnCurrentExtension(&myself, is_replace);
2033
2034
  /* Post creation hook for new transform */
2035
0
  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
2036
2037
0
  heap_freetuple(newtuple);
2038
2039
0
  table_close(relation, RowExclusiveLock);
2040
2041
0
  return myself;
2042
0
}
2043
2044
2045
/*
2046
 * get_transform_oid - given type OID and language OID, look up a transform OID
2047
 *
2048
 * If missing_ok is false, throw an error if the transform is not found.  If
2049
 * true, just return InvalidOid.
2050
 */
2051
Oid
2052
get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
2053
0
{
2054
0
  Oid     oid;
2055
2056
0
  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2057
0
              ObjectIdGetDatum(type_id),
2058
0
              ObjectIdGetDatum(lang_id));
2059
0
  if (!OidIsValid(oid) && !missing_ok)
2060
0
    ereport(ERROR,
2061
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
2062
0
         errmsg("transform for type %s language \"%s\" does not exist",
2063
0
            format_type_be(type_id),
2064
0
            get_language_name(lang_id, false))));
2065
0
  return oid;
2066
0
}
2067
2068
2069
/*
2070
 * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME
2071
 *
2072
 * Is there a function with the given name and signature already in the given
2073
 * namespace?  If so, raise an appropriate error message.
2074
 */
2075
void
2076
IsThereFunctionInNamespace(const char *proname, int pronargs,
2077
               oidvector *proargtypes, Oid nspOid)
2078
0
{
2079
  /* check for duplicate name (more friendly than unique-index failure) */
2080
0
  if (SearchSysCacheExists3(PROCNAMEARGSNSP,
2081
0
                CStringGetDatum(proname),
2082
0
                PointerGetDatum(proargtypes),
2083
0
                ObjectIdGetDatum(nspOid)))
2084
0
    ereport(ERROR,
2085
0
        (errcode(ERRCODE_DUPLICATE_FUNCTION),
2086
0
         errmsg("function %s already exists in schema \"%s\"",
2087
0
            funcname_signature_string(proname, pronargs,
2088
0
                          NIL, proargtypes->values),
2089
0
            get_namespace_name(nspOid))));
2090
0
}
2091
2092
/*
2093
 * ExecuteDoStmt
2094
 *    Execute inline procedural-language code
2095
 *
2096
 * See at ExecuteCallStmt() about the atomic argument.
2097
 */
2098
void
2099
ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
2100
0
{
2101
0
  InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
2102
0
  ListCell   *arg;
2103
0
  DefElem    *as_item = NULL;
2104
0
  DefElem    *language_item = NULL;
2105
0
  char     *language;
2106
0
  Oid     laninline;
2107
0
  HeapTuple languageTuple;
2108
0
  Form_pg_language languageStruct;
2109
2110
  /* Process options we got from gram.y */
2111
0
  foreach(arg, stmt->args)
2112
0
  {
2113
0
    DefElem    *defel = (DefElem *) lfirst(arg);
2114
2115
0
    if (strcmp(defel->defname, "as") == 0)
2116
0
    {
2117
0
      if (as_item)
2118
0
        errorConflictingDefElem(defel, pstate);
2119
0
      as_item = defel;
2120
0
    }
2121
0
    else if (strcmp(defel->defname, "language") == 0)
2122
0
    {
2123
0
      if (language_item)
2124
0
        errorConflictingDefElem(defel, pstate);
2125
0
      language_item = defel;
2126
0
    }
2127
0
    else
2128
0
      elog(ERROR, "option \"%s\" not recognized",
2129
0
         defel->defname);
2130
0
  }
2131
2132
0
  if (as_item)
2133
0
    codeblock->source_text = strVal(as_item->arg);
2134
0
  else
2135
0
    ereport(ERROR,
2136
0
        (errcode(ERRCODE_SYNTAX_ERROR),
2137
0
         errmsg("no inline code specified")));
2138
2139
  /* if LANGUAGE option wasn't specified, use the default */
2140
0
  if (language_item)
2141
0
    language = strVal(language_item->arg);
2142
0
  else
2143
0
    language = "plpgsql";
2144
2145
  /* Look up the language and validate permissions */
2146
0
  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2147
0
  if (!HeapTupleIsValid(languageTuple))
2148
0
    ereport(ERROR,
2149
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
2150
0
         errmsg("language \"%s\" does not exist", language),
2151
0
         (extension_file_exists(language) ?
2152
0
          errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2153
2154
0
  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2155
0
  codeblock->langOid = languageStruct->oid;
2156
0
  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2157
0
  codeblock->atomic = atomic;
2158
2159
0
  if (languageStruct->lanpltrusted)
2160
0
  {
2161
    /* if trusted language, need USAGE privilege */
2162
0
    AclResult aclresult;
2163
2164
0
    aclresult = object_aclcheck(LanguageRelationId, codeblock->langOid, GetUserId(),
2165
0
                  ACL_USAGE);
2166
0
    if (aclresult != ACLCHECK_OK)
2167
0
      aclcheck_error(aclresult, OBJECT_LANGUAGE,
2168
0
               NameStr(languageStruct->lanname));
2169
0
  }
2170
0
  else
2171
0
  {
2172
    /* if untrusted language, must be superuser */
2173
0
    if (!superuser())
2174
0
      aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
2175
0
               NameStr(languageStruct->lanname));
2176
0
  }
2177
2178
  /* get the handler function's OID */
2179
0
  laninline = languageStruct->laninline;
2180
0
  if (!OidIsValid(laninline))
2181
0
    ereport(ERROR,
2182
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2183
0
         errmsg("language \"%s\" does not support inline code execution",
2184
0
            NameStr(languageStruct->lanname))));
2185
2186
0
  ReleaseSysCache(languageTuple);
2187
2188
  /* execute the inline handler */
2189
0
  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2190
0
}
2191
2192
/*
2193
 * Execute CALL statement
2194
 *
2195
 * Inside a top-level CALL statement, transaction-terminating commands such as
2196
 * COMMIT or a PL-specific equivalent are allowed.  The terminology in the SQL
2197
 * standard is that CALL establishes a non-atomic execution context.  Most
2198
 * other commands establish an atomic execution context, in which transaction
2199
 * control actions are not allowed.  If there are nested executions of CALL,
2200
 * we want to track the execution context recursively, so that the nested
2201
 * CALLs can also do transaction control.  Note, however, that for example in
2202
 * CALL -> SELECT -> CALL, the second call cannot do transaction control,
2203
 * because the SELECT in between establishes an atomic execution context.
2204
 *
2205
 * So when ExecuteCallStmt() is called from the top level, we pass in atomic =
2206
 * false (recall that that means transactions = yes).  We then create a
2207
 * CallContext node with content atomic = false, which is passed in the
2208
 * fcinfo->context field to the procedure invocation.  The language
2209
 * implementation should then take appropriate measures to allow or prevent
2210
 * transaction commands based on that information, e.g., call
2211
 * SPI_connect_ext(SPI_OPT_NONATOMIC).  The language should also pass on the
2212
 * atomic flag to any nested invocations to CALL.
2213
 *
2214
 * The expression data structures and execution context that we create
2215
 * within this function are children of the portalContext of the Portal
2216
 * that the CALL utility statement runs in.  Therefore, any pass-by-ref
2217
 * values that we're passing to the procedure will survive transaction
2218
 * commits that might occur inside the procedure.
2219
 */
2220
void
2221
ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
2222
0
{
2223
0
  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2224
0
  ListCell   *lc;
2225
0
  FuncExpr   *fexpr;
2226
0
  int     nargs;
2227
0
  int     i;
2228
0
  AclResult aclresult;
2229
0
  FmgrInfo  flinfo;
2230
0
  CallContext *callcontext;
2231
0
  EState     *estate;
2232
0
  ExprContext *econtext;
2233
0
  HeapTuple tp;
2234
0
  PgStat_FunctionCallUsage fcusage;
2235
0
  Datum   retval;
2236
2237
0
  fexpr = stmt->funcexpr;
2238
0
  Assert(fexpr);
2239
0
  Assert(IsA(fexpr, FuncExpr));
2240
2241
0
  aclresult = object_aclcheck(ProcedureRelationId, fexpr->funcid, GetUserId(), ACL_EXECUTE);
2242
0
  if (aclresult != ACLCHECK_OK)
2243
0
    aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2244
2245
  /* Prep the context object we'll pass to the procedure */
2246
0
  callcontext = makeNode(CallContext);
2247
0
  callcontext->atomic = atomic;
2248
2249
0
  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2250
0
  if (!HeapTupleIsValid(tp))
2251
0
    elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2252
2253
  /*
2254
   * If proconfig is set we can't allow transaction commands because of the
2255
   * way the GUC stacking works: The transaction boundary would have to pop
2256
   * the proconfig setting off the stack.  That restriction could be lifted
2257
   * by redesigning the GUC nesting mechanism a bit.
2258
   */
2259
0
  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2260
0
    callcontext->atomic = true;
2261
2262
  /*
2263
   * In security definer procedures, we can't allow transaction commands.
2264
   * StartTransaction() insists that the security context stack is empty,
2265
   * and AbortTransaction() resets the security context.  This could be
2266
   * reorganized, but right now it doesn't work.
2267
   */
2268
0
  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2269
0
    callcontext->atomic = true;
2270
2271
0
  ReleaseSysCache(tp);
2272
2273
  /* safety check; see ExecInitFunc() */
2274
0
  nargs = list_length(fexpr->args);
2275
0
  if (nargs > FUNC_MAX_ARGS)
2276
0
    ereport(ERROR,
2277
0
        (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2278
0
         errmsg_plural("cannot pass more than %d argument to a procedure",
2279
0
                 "cannot pass more than %d arguments to a procedure",
2280
0
                 FUNC_MAX_ARGS,
2281
0
                 FUNC_MAX_ARGS)));
2282
2283
  /* Initialize function call structure */
2284
0
  InvokeFunctionExecuteHook(fexpr->funcid);
2285
0
  fmgr_info(fexpr->funcid, &flinfo);
2286
0
  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2287
0
  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2288
0
               (Node *) callcontext, NULL);
2289
2290
  /*
2291
   * Evaluate procedure arguments inside a suitable execution context.  Note
2292
   * we can't free this context till the procedure returns.
2293
   */
2294
0
  estate = CreateExecutorState();
2295
0
  estate->es_param_list_info = params;
2296
0
  econtext = CreateExprContext(estate);
2297
2298
  /*
2299
   * If we're called in non-atomic context, we also have to ensure that the
2300
   * argument expressions run with an up-to-date snapshot.  Our caller will
2301
   * have provided a current snapshot in atomic contexts, but not in
2302
   * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2303
   * destroying the snapshot makes higher-level management too complicated.
2304
   */
2305
0
  if (!atomic)
2306
0
    PushActiveSnapshot(GetTransactionSnapshot());
2307
2308
0
  i = 0;
2309
0
  foreach(lc, fexpr->args)
2310
0
  {
2311
0
    ExprState  *exprstate;
2312
0
    Datum   val;
2313
0
    bool    isnull;
2314
2315
0
    exprstate = ExecPrepareExpr(lfirst(lc), estate);
2316
2317
0
    val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2318
2319
0
    fcinfo->args[i].value = val;
2320
0
    fcinfo->args[i].isnull = isnull;
2321
2322
0
    i++;
2323
0
  }
2324
2325
  /* Get rid of temporary snapshot for arguments, if we made one */
2326
0
  if (!atomic)
2327
0
    PopActiveSnapshot();
2328
2329
  /* Here we actually call the procedure */
2330
0
  pgstat_init_function_usage(fcinfo, &fcusage);
2331
0
  retval = FunctionCallInvoke(fcinfo);
2332
0
  pgstat_end_function_usage(&fcusage, true);
2333
2334
  /* Handle the procedure's outputs */
2335
0
  if (fexpr->funcresulttype == VOIDOID)
2336
0
  {
2337
    /* do nothing */
2338
0
  }
2339
0
  else if (fexpr->funcresulttype == RECORDOID)
2340
0
  {
2341
    /* send tuple to client */
2342
0
    HeapTupleHeader td;
2343
0
    Oid     tupType;
2344
0
    int32   tupTypmod;
2345
0
    TupleDesc retdesc;
2346
0
    HeapTupleData rettupdata;
2347
0
    TupOutputState *tstate;
2348
0
    TupleTableSlot *slot;
2349
2350
0
    if (fcinfo->isnull)
2351
0
      elog(ERROR, "procedure returned null record");
2352
2353
    /*
2354
     * Ensure there's an active snapshot whilst we execute whatever's
2355
     * involved here.  Note that this is *not* sufficient to make the
2356
     * world safe for TOAST pointers to be included in the returned data:
2357
     * the referenced data could have gone away while we didn't hold a
2358
     * snapshot.  Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2359
     * to not return TOAST pointers, unless those pointers were fetched
2360
     * after the last COMMIT/ROLLBACK in the procedure.
2361
     *
2362
     * XXX that is a really nasty, hard-to-test requirement.  Is there a
2363
     * way to remove it?
2364
     */
2365
0
    EnsurePortalSnapshotExists();
2366
2367
0
    td = DatumGetHeapTupleHeader(retval);
2368
0
    tupType = HeapTupleHeaderGetTypeId(td);
2369
0
    tupTypmod = HeapTupleHeaderGetTypMod(td);
2370
0
    retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2371
2372
0
    tstate = begin_tup_output_tupdesc(dest, retdesc,
2373
0
                      &TTSOpsHeapTuple);
2374
2375
0
    rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2376
0
    ItemPointerSetInvalid(&(rettupdata.t_self));
2377
0
    rettupdata.t_tableOid = InvalidOid;
2378
0
    rettupdata.t_data = td;
2379
2380
0
    slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2381
0
    tstate->dest->receiveSlot(slot, tstate->dest);
2382
2383
0
    end_tup_output(tstate);
2384
2385
0
    ReleaseTupleDesc(retdesc);
2386
0
  }
2387
0
  else
2388
0
    elog(ERROR, "unexpected result type for procedure: %u",
2389
0
       fexpr->funcresulttype);
2390
2391
0
  FreeExecutorState(estate);
2392
0
}
2393
2394
/*
2395
 * Construct the tuple descriptor for a CALL statement return
2396
 */
2397
TupleDesc
2398
CallStmtResultDesc(CallStmt *stmt)
2399
0
{
2400
0
  FuncExpr   *fexpr;
2401
0
  HeapTuple tuple;
2402
0
  TupleDesc tupdesc;
2403
2404
0
  fexpr = stmt->funcexpr;
2405
2406
0
  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2407
0
  if (!HeapTupleIsValid(tuple))
2408
0
    elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2409
2410
0
  tupdesc = build_function_result_tupdesc_t(tuple);
2411
2412
0
  ReleaseSysCache(tuple);
2413
2414
  /*
2415
   * The result of build_function_result_tupdesc_t has the right column
2416
   * names, but it just has the declared output argument types, which is the
2417
   * wrong thing in polymorphic cases.  Get the correct types by examining
2418
   * stmt->outargs.  We intentionally keep the atttypmod as -1 and the
2419
   * attcollation as the type's default, since that's always the appropriate
2420
   * thing for function outputs; there's no point in considering any
2421
   * additional info available from outargs.  Note that tupdesc is null if
2422
   * there are no outargs.
2423
   */
2424
0
  if (tupdesc)
2425
0
  {
2426
0
    Assert(tupdesc->natts == list_length(stmt->outargs));
2427
0
    for (int i = 0; i < tupdesc->natts; i++)
2428
0
    {
2429
0
      Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2430
0
      Node     *outarg = (Node *) list_nth(stmt->outargs, i);
2431
2432
0
      TupleDescInitEntry(tupdesc,
2433
0
                 i + 1,
2434
0
                 NameStr(att->attname),
2435
0
                 exprType(outarg),
2436
0
                 -1,
2437
0
                 0);
2438
0
    }
2439
0
    TupleDescFinalize(tupdesc);
2440
0
  }
2441
2442
0
  return tupdesc;
2443
0
}