]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_proc.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / catalog / pg_proc.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_proc.c
4  *        routines to support manipulation of the pg_proc relation
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/catalog/pg_proc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "access/xact.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/objectaccess.h"
24 #include "catalog/pg_language.h"
25 #include "catalog/pg_namespace.h"
26 #include "catalog/pg_proc.h"
27 #include "catalog/pg_transform.h"
28 #include "catalog/pg_type.h"
29 #include "commands/defrem.h"
30 #include "executor/functions.h"
31 #include "funcapi.h"
32 #include "mb/pg_wchar.h"
33 #include "miscadmin.h"
34 #include "nodes/nodeFuncs.h"
35 #include "parser/parse_type.h"
36 #include "tcop/pquery.h"
37 #include "tcop/tcopprot.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/lsyscache.h"
41 #include "utils/regproc.h"
42 #include "utils/rel.h"
43 #include "utils/syscache.h"
44
45
46 typedef struct
47 {
48         char       *proname;
49         char       *prosrc;
50 } parse_error_callback_arg;
51
52 static void sql_function_parse_error_callback(void *arg);
53 static int      match_prosrc_to_query(const char *prosrc, const char *queryText,
54                                                                   int cursorpos);
55 static bool match_prosrc_to_literal(const char *prosrc, const char *literal,
56                                                                         int cursorpos, int *newcursorpos);
57
58
59 /* ----------------------------------------------------------------
60  *              ProcedureCreate
61  *
62  * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig
63  * are either arrays of the proper types or NULL.  We declare them Datum,
64  * not "ArrayType *", to avoid importing array.h into pg_proc.h.
65  * ----------------------------------------------------------------
66  */
67 ObjectAddress
68 ProcedureCreate(const char *procedureName,
69                                 Oid procNamespace,
70                                 bool replace,
71                                 bool returnsSet,
72                                 Oid returnType,
73                                 Oid proowner,
74                                 Oid languageObjectId,
75                                 Oid languageValidator,
76                                 const char *prosrc,
77                                 const char *probin,
78                                 char prokind,
79                                 bool security_definer,
80                                 bool isLeakProof,
81                                 bool isStrict,
82                                 char volatility,
83                                 char parallel,
84                                 oidvector *parameterTypes,
85                                 Datum allParameterTypes,
86                                 Datum parameterModes,
87                                 Datum parameterNames,
88                                 List *parameterDefaults,
89                                 Datum trftypes,
90                                 Datum proconfig,
91                                 Oid prosupport,
92                                 float4 procost,
93                                 float4 prorows)
94 {
95         Oid                     retval;
96         int                     parameterCount;
97         int                     allParamCount;
98         Oid                *allParams;
99         char       *paramModes = NULL;
100         bool            genericInParam = false;
101         bool            genericOutParam = false;
102         bool            anyrangeInParam = false;
103         bool            anyrangeOutParam = false;
104         bool            internalInParam = false;
105         bool            internalOutParam = false;
106         Oid                     variadicType = InvalidOid;
107         Acl                *proacl = NULL;
108         Relation        rel;
109         HeapTuple       tup;
110         HeapTuple       oldtup;
111         bool            nulls[Natts_pg_proc];
112         Datum           values[Natts_pg_proc];
113         bool            replaces[Natts_pg_proc];
114         NameData        procname;
115         TupleDesc       tupDesc;
116         bool            is_update;
117         ObjectAddress myself,
118                                 referenced;
119         int                     i;
120         Oid                     trfid;
121
122         /*
123          * sanity checks
124          */
125         Assert(PointerIsValid(prosrc));
126
127         parameterCount = parameterTypes->dim1;
128         if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
129                 ereport(ERROR,
130                                 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
131                                  errmsg_plural("functions cannot have more than %d argument",
132                                                            "functions cannot have more than %d arguments",
133                                                            FUNC_MAX_ARGS,
134                                                            FUNC_MAX_ARGS)));
135         /* note: the above is correct, we do NOT count output arguments */
136
137         /* Deconstruct array inputs */
138         if (allParameterTypes != PointerGetDatum(NULL))
139         {
140                 /*
141                  * We expect the array to be a 1-D OID array; verify that. We don't
142                  * need to use deconstruct_array() since the array data is just going
143                  * to look like a C array of OID values.
144                  */
145                 ArrayType  *allParamArray = (ArrayType *) DatumGetPointer(allParameterTypes);
146
147                 allParamCount = ARR_DIMS(allParamArray)[0];
148                 if (ARR_NDIM(allParamArray) != 1 ||
149                         allParamCount <= 0 ||
150                         ARR_HASNULL(allParamArray) ||
151                         ARR_ELEMTYPE(allParamArray) != OIDOID)
152                         elog(ERROR, "allParameterTypes is not a 1-D Oid array");
153                 allParams = (Oid *) ARR_DATA_PTR(allParamArray);
154                 Assert(allParamCount >= parameterCount);
155                 /* we assume caller got the contents right */
156         }
157         else
158         {
159                 allParamCount = parameterCount;
160                 allParams = parameterTypes->values;
161         }
162
163         if (parameterModes != PointerGetDatum(NULL))
164         {
165                 /*
166                  * We expect the array to be a 1-D CHAR array; verify that. We don't
167                  * need to use deconstruct_array() since the array data is just going
168                  * to look like a C array of char values.
169                  */
170                 ArrayType  *modesArray = (ArrayType *) DatumGetPointer(parameterModes);
171
172                 if (ARR_NDIM(modesArray) != 1 ||
173                         ARR_DIMS(modesArray)[0] != allParamCount ||
174                         ARR_HASNULL(modesArray) ||
175                         ARR_ELEMTYPE(modesArray) != CHAROID)
176                         elog(ERROR, "parameterModes is not a 1-D char array");
177                 paramModes = (char *) ARR_DATA_PTR(modesArray);
178         }
179
180         /*
181          * Detect whether we have polymorphic or INTERNAL arguments.  The first
182          * loop checks input arguments, the second output arguments.
183          */
184         for (i = 0; i < parameterCount; i++)
185         {
186                 switch (parameterTypes->values[i])
187                 {
188                         case ANYARRAYOID:
189                         case ANYELEMENTOID:
190                         case ANYNONARRAYOID:
191                         case ANYENUMOID:
192                                 genericInParam = true;
193                                 break;
194                         case ANYRANGEOID:
195                                 genericInParam = true;
196                                 anyrangeInParam = true;
197                                 break;
198                         case INTERNALOID:
199                                 internalInParam = true;
200                                 break;
201                 }
202         }
203
204         if (allParameterTypes != PointerGetDatum(NULL))
205         {
206                 for (i = 0; i < allParamCount; i++)
207                 {
208                         if (paramModes == NULL ||
209                                 paramModes[i] == PROARGMODE_IN ||
210                                 paramModes[i] == PROARGMODE_VARIADIC)
211                                 continue;               /* ignore input-only params */
212
213                         switch (allParams[i])
214                         {
215                                 case ANYARRAYOID:
216                                 case ANYELEMENTOID:
217                                 case ANYNONARRAYOID:
218                                 case ANYENUMOID:
219                                         genericOutParam = true;
220                                         break;
221                                 case ANYRANGEOID:
222                                         genericOutParam = true;
223                                         anyrangeOutParam = true;
224                                         break;
225                                 case INTERNALOID:
226                                         internalOutParam = true;
227                                         break;
228                         }
229                 }
230         }
231
232         /*
233          * Do not allow polymorphic return type unless at least one input argument
234          * is polymorphic.  ANYRANGE return type is even stricter: must have an
235          * ANYRANGE input (since we can't deduce the specific range type from
236          * ANYELEMENT).  Also, do not allow return type INTERNAL unless at least
237          * one input argument is INTERNAL.
238          */
239         if ((IsPolymorphicType(returnType) || genericOutParam)
240                 && !genericInParam)
241                 ereport(ERROR,
242                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
243                                  errmsg("cannot determine result data type"),
244                                  errdetail("A function returning a polymorphic type must have at least one polymorphic argument.")));
245
246         if ((returnType == ANYRANGEOID || anyrangeOutParam) &&
247                 !anyrangeInParam)
248                 ereport(ERROR,
249                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
250                                  errmsg("cannot determine result data type"),
251                                  errdetail("A function returning \"anyrange\" must have at least one \"anyrange\" argument.")));
252
253         if ((returnType == INTERNALOID || internalOutParam) && !internalInParam)
254                 ereport(ERROR,
255                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
256                                  errmsg("unsafe use of pseudo-type \"internal\""),
257                                  errdetail("A function returning \"internal\" must have at least one \"internal\" argument.")));
258
259         if (paramModes != NULL)
260         {
261                 /*
262                  * Only the last input parameter can be variadic; if it is, save its
263                  * element type.  Errors here are just elog since caller should have
264                  * checked this already.
265                  */
266                 for (i = 0; i < allParamCount; i++)
267                 {
268                         switch (paramModes[i])
269                         {
270                                 case PROARGMODE_IN:
271                                 case PROARGMODE_INOUT:
272                                         if (OidIsValid(variadicType))
273                                                 elog(ERROR, "variadic parameter must be last");
274                                         break;
275                                 case PROARGMODE_OUT:
276                                 case PROARGMODE_TABLE:
277                                         /* okay */
278                                         break;
279                                 case PROARGMODE_VARIADIC:
280                                         if (OidIsValid(variadicType))
281                                                 elog(ERROR, "variadic parameter must be last");
282                                         switch (allParams[i])
283                                         {
284                                                 case ANYOID:
285                                                         variadicType = ANYOID;
286                                                         break;
287                                                 case ANYARRAYOID:
288                                                         variadicType = ANYELEMENTOID;
289                                                         break;
290                                                 default:
291                                                         variadicType = get_element_type(allParams[i]);
292                                                         if (!OidIsValid(variadicType))
293                                                                 elog(ERROR, "variadic parameter is not an array");
294                                                         break;
295                                         }
296                                         break;
297                                 default:
298                                         elog(ERROR, "invalid parameter mode '%c'", paramModes[i]);
299                                         break;
300                         }
301                 }
302         }
303
304         /*
305          * All seems OK; prepare the data to be inserted into pg_proc.
306          */
307
308         for (i = 0; i < Natts_pg_proc; ++i)
309         {
310                 nulls[i] = false;
311                 values[i] = (Datum) 0;
312                 replaces[i] = true;
313         }
314
315         namestrcpy(&procname, procedureName);
316         values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname);
317         values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace);
318         values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner);
319         values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId);
320         values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost);
321         values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows);
322         values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType);
323         values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport);
324         values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind);
325         values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer);
326         values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof);
327         values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict);
328         values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
329         values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
330         values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel);
331         values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
332         values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults));
333         values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
334         values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
335         if (allParameterTypes != PointerGetDatum(NULL))
336                 values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
337         else
338                 nulls[Anum_pg_proc_proallargtypes - 1] = true;
339         if (parameterModes != PointerGetDatum(NULL))
340                 values[Anum_pg_proc_proargmodes - 1] = parameterModes;
341         else
342                 nulls[Anum_pg_proc_proargmodes - 1] = true;
343         if (parameterNames != PointerGetDatum(NULL))
344                 values[Anum_pg_proc_proargnames - 1] = parameterNames;
345         else
346                 nulls[Anum_pg_proc_proargnames - 1] = true;
347         if (parameterDefaults != NIL)
348                 values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
349         else
350                 nulls[Anum_pg_proc_proargdefaults - 1] = true;
351         if (trftypes != PointerGetDatum(NULL))
352                 values[Anum_pg_proc_protrftypes - 1] = trftypes;
353         else
354                 nulls[Anum_pg_proc_protrftypes - 1] = true;
355         values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
356         if (probin)
357                 values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
358         else
359                 nulls[Anum_pg_proc_probin - 1] = true;
360         if (proconfig != PointerGetDatum(NULL))
361                 values[Anum_pg_proc_proconfig - 1] = proconfig;
362         else
363                 nulls[Anum_pg_proc_proconfig - 1] = true;
364         /* proacl will be determined later */
365
366         rel = table_open(ProcedureRelationId, RowExclusiveLock);
367         tupDesc = RelationGetDescr(rel);
368
369         /* Check for pre-existing definition */
370         oldtup = SearchSysCache3(PROCNAMEARGSNSP,
371                                                          PointerGetDatum(procedureName),
372                                                          PointerGetDatum(parameterTypes),
373                                                          ObjectIdGetDatum(procNamespace));
374
375         if (HeapTupleIsValid(oldtup))
376         {
377                 /* There is one; okay to replace it? */
378                 Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
379                 Datum           proargnames;
380                 bool            isnull;
381                 const char *dropcmd;
382
383                 if (!replace)
384                         ereport(ERROR,
385                                         (errcode(ERRCODE_DUPLICATE_FUNCTION),
386                                          errmsg("function \"%s\" already exists with same argument types",
387                                                         procedureName)));
388                 if (!pg_proc_ownercheck(oldproc->oid, proowner))
389                         aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
390                                                    procedureName);
391
392                 /* Not okay to change routine kind */
393                 if (oldproc->prokind != prokind)
394                         ereport(ERROR,
395                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
396                                          errmsg("cannot change routine kind"),
397                                          (oldproc->prokind == PROKIND_AGGREGATE ?
398                                           errdetail("\"%s\" is an aggregate function.", procedureName) :
399                                           oldproc->prokind == PROKIND_FUNCTION ?
400                                           errdetail("\"%s\" is a function.", procedureName) :
401                                           oldproc->prokind == PROKIND_PROCEDURE ?
402                                           errdetail("\"%s\" is a procedure.", procedureName) :
403                                           oldproc->prokind == PROKIND_WINDOW ?
404                                           errdetail("\"%s\" is a window function.", procedureName) :
405                                           0)));
406
407                 dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
408                                    prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
409                                    "DROP FUNCTION");
410
411                 /*
412                  * Not okay to change the return type of the existing proc, since
413                  * existing rules, views, etc may depend on the return type.
414                  *
415                  * In case of a procedure, a changing return type means that whether
416                  * the procedure has output parameters was changed.  Since there is no
417                  * user visible return type, we produce a more specific error message.
418                  */
419                 if (returnType != oldproc->prorettype ||
420                         returnsSet != oldproc->proretset)
421                         ereport(ERROR,
422                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
423                                          prokind == PROKIND_PROCEDURE
424                                          ? errmsg("cannot change whether a procedure has output parameters")
425                                          : errmsg("cannot change return type of existing function"),
426
427                         /*
428                          * translator: first %s is DROP FUNCTION, DROP PROCEDURE, or DROP
429                          * AGGREGATE
430                          */
431                                          errhint("Use %s %s first.",
432                                                          dropcmd,
433                                                          format_procedure(oldproc->oid))));
434
435                 /*
436                  * If it returns RECORD, check for possible change of record type
437                  * implied by OUT parameters
438                  */
439                 if (returnType == RECORDOID)
440                 {
441                         TupleDesc       olddesc;
442                         TupleDesc       newdesc;
443
444                         olddesc = build_function_result_tupdesc_t(oldtup);
445                         newdesc = build_function_result_tupdesc_d(prokind,
446                                                                                                           allParameterTypes,
447                                                                                                           parameterModes,
448                                                                                                           parameterNames);
449                         if (olddesc == NULL && newdesc == NULL)
450                                  /* ok, both are runtime-defined RECORDs */ ;
451                         else if (olddesc == NULL || newdesc == NULL ||
452                                          !equalTupleDescs(olddesc, newdesc))
453                                 ereport(ERROR,
454                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
455                                                  errmsg("cannot change return type of existing function"),
456                                                  errdetail("Row type defined by OUT parameters is different."),
457                                 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
458                                                  errhint("Use %s %s first.",
459                                                                  dropcmd,
460                                                                  format_procedure(oldproc->oid))));
461                 }
462
463                 /*
464                  * If there were any named input parameters, check to make sure the
465                  * names have not been changed, as this could break existing calls. We
466                  * allow adding names to formerly unnamed parameters, though.
467                  */
468                 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
469                                                                           Anum_pg_proc_proargnames,
470                                                                           &isnull);
471                 if (!isnull)
472                 {
473                         Datum           proargmodes;
474                         char      **old_arg_names;
475                         char      **new_arg_names;
476                         int                     n_old_arg_names;
477                         int                     n_new_arg_names;
478                         int                     j;
479
480                         proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
481                                                                                   Anum_pg_proc_proargmodes,
482                                                                                   &isnull);
483                         if (isnull)
484                                 proargmodes = PointerGetDatum(NULL);    /* just to be sure */
485
486                         n_old_arg_names = get_func_input_arg_names(proargnames,
487                                                                                                            proargmodes,
488                                                                                                            &old_arg_names);
489                         n_new_arg_names = get_func_input_arg_names(parameterNames,
490                                                                                                            parameterModes,
491                                                                                                            &new_arg_names);
492                         for (j = 0; j < n_old_arg_names; j++)
493                         {
494                                 if (old_arg_names[j] == NULL)
495                                         continue;
496                                 if (j >= n_new_arg_names || new_arg_names[j] == NULL ||
497                                         strcmp(old_arg_names[j], new_arg_names[j]) != 0)
498                                         ereport(ERROR,
499                                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
500                                                          errmsg("cannot change name of input parameter \"%s\"",
501                                                                         old_arg_names[j]),
502                                         /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
503                                                          errhint("Use %s %s first.",
504                                                                          dropcmd,
505                                                                          format_procedure(oldproc->oid))));
506                         }
507                 }
508
509                 /*
510                  * If there are existing defaults, check compatibility: redefinition
511                  * must not remove any defaults nor change their types.  (Removing a
512                  * default might cause a function to fail to satisfy an existing call.
513                  * Changing type would only be possible if the associated parameter is
514                  * polymorphic, and in such cases a change of default type might alter
515                  * the resolved output type of existing calls.)
516                  */
517                 if (oldproc->pronargdefaults != 0)
518                 {
519                         Datum           proargdefaults;
520                         List       *oldDefaults;
521                         ListCell   *oldlc;
522                         ListCell   *newlc;
523
524                         if (list_length(parameterDefaults) < oldproc->pronargdefaults)
525                                 ereport(ERROR,
526                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
527                                                  errmsg("cannot remove parameter defaults from existing function"),
528                                 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
529                                                  errhint("Use %s %s first.",
530                                                                  dropcmd,
531                                                                  format_procedure(oldproc->oid))));
532
533                         proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
534                                                                                          Anum_pg_proc_proargdefaults,
535                                                                                          &isnull);
536                         Assert(!isnull);
537                         oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults)));
538                         Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
539
540                         /* new list can have more defaults than old, advance over 'em */
541                         newlc = list_nth_cell(parameterDefaults,
542                                                                   list_length(parameterDefaults) -
543                                                                   oldproc->pronargdefaults);
544
545                         foreach(oldlc, oldDefaults)
546                         {
547                                 Node       *oldDef = (Node *) lfirst(oldlc);
548                                 Node       *newDef = (Node *) lfirst(newlc);
549
550                                 if (exprType(oldDef) != exprType(newDef))
551                                         ereport(ERROR,
552                                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
553                                                          errmsg("cannot change data type of existing parameter default value"),
554                                         /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
555                                                          errhint("Use %s %s first.",
556                                                                          dropcmd,
557                                                                          format_procedure(oldproc->oid))));
558                                 newlc = lnext(parameterDefaults, newlc);
559                         }
560                 }
561
562                 /*
563                  * Do not change existing oid, ownership or permissions, either.  Note
564                  * dependency-update code below has to agree with this decision.
565                  */
566                 replaces[Anum_pg_proc_oid - 1] = false;
567                 replaces[Anum_pg_proc_proowner - 1] = false;
568                 replaces[Anum_pg_proc_proacl - 1] = false;
569
570                 /* Okay, do it... */
571                 tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
572                 CatalogTupleUpdate(rel, &tup->t_self, tup);
573
574                 ReleaseSysCache(oldtup);
575                 is_update = true;
576         }
577         else
578         {
579                 /* Creating a new procedure */
580                 Oid                     newOid;
581
582                 /* First, get default permissions and set up proacl */
583                 proacl = get_user_default_acl(OBJECT_FUNCTION, proowner,
584                                                                           procNamespace);
585                 if (proacl != NULL)
586                         values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl);
587                 else
588                         nulls[Anum_pg_proc_proacl - 1] = true;
589
590                 newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId,
591                                                                         Anum_pg_proc_oid);
592                 values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid);
593                 tup = heap_form_tuple(tupDesc, values, nulls);
594                 CatalogTupleInsert(rel, tup);
595                 is_update = false;
596         }
597
598
599         retval = ((Form_pg_proc) GETSTRUCT(tup))->oid;
600
601         /*
602          * Create dependencies for the new function.  If we are updating an
603          * existing function, first delete any existing pg_depend entries.
604          * (However, since we are not changing ownership or permissions, the
605          * shared dependencies do *not* need to change, and we leave them alone.)
606          */
607         if (is_update)
608                 deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
609
610         myself.classId = ProcedureRelationId;
611         myself.objectId = retval;
612         myself.objectSubId = 0;
613
614         /* dependency on namespace */
615         referenced.classId = NamespaceRelationId;
616         referenced.objectId = procNamespace;
617         referenced.objectSubId = 0;
618         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
619
620         /* dependency on implementation language */
621         referenced.classId = LanguageRelationId;
622         referenced.objectId = languageObjectId;
623         referenced.objectSubId = 0;
624         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
625
626         /* dependency on return type */
627         referenced.classId = TypeRelationId;
628         referenced.objectId = returnType;
629         referenced.objectSubId = 0;
630         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
631
632         /* dependency on transform used by return type, if any */
633         if ((trfid = get_transform_oid(returnType, languageObjectId, true)))
634         {
635                 referenced.classId = TransformRelationId;
636                 referenced.objectId = trfid;
637                 referenced.objectSubId = 0;
638                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
639         }
640
641         /* dependency on parameter types */
642         for (i = 0; i < allParamCount; i++)
643         {
644                 referenced.classId = TypeRelationId;
645                 referenced.objectId = allParams[i];
646                 referenced.objectSubId = 0;
647                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
648
649                 /* dependency on transform used by parameter type, if any */
650                 if ((trfid = get_transform_oid(allParams[i], languageObjectId, true)))
651                 {
652                         referenced.classId = TransformRelationId;
653                         referenced.objectId = trfid;
654                         referenced.objectSubId = 0;
655                         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
656                 }
657         }
658
659         /* dependency on parameter default expressions */
660         if (parameterDefaults)
661                 recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
662                                                            NIL, DEPENDENCY_NORMAL);
663
664         /* dependency on support function, if any */
665         if (OidIsValid(prosupport))
666         {
667                 referenced.classId = ProcedureRelationId;
668                 referenced.objectId = prosupport;
669                 referenced.objectSubId = 0;
670                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
671         }
672
673         /* dependency on owner */
674         if (!is_update)
675                 recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
676
677         /* dependency on any roles mentioned in ACL */
678         if (!is_update)
679                 recordDependencyOnNewAcl(ProcedureRelationId, retval, 0,
680                                                                  proowner, proacl);
681
682         /* dependency on extension */
683         recordDependencyOnCurrentExtension(&myself, is_update);
684
685         heap_freetuple(tup);
686
687         /* Post creation hook for new function */
688         InvokeObjectPostCreateHook(ProcedureRelationId, retval, 0);
689
690         table_close(rel, RowExclusiveLock);
691
692         /* Verify function body */
693         if (OidIsValid(languageValidator))
694         {
695                 ArrayType  *set_items = NULL;
696                 int                     save_nestlevel = 0;
697
698                 /* Advance command counter so new tuple can be seen by validator */
699                 CommandCounterIncrement();
700
701                 /*
702                  * Set per-function configuration parameters so that the validation is
703                  * done with the environment the function expects.  However, if
704                  * check_function_bodies is off, we don't do this, because that would
705                  * create dump ordering hazards that pg_dump doesn't know how to deal
706                  * with.  (For example, a SET clause might refer to a not-yet-created
707                  * text search configuration.)  This means that the validator
708                  * shouldn't complain about anything that might depend on a GUC
709                  * parameter when check_function_bodies is off.
710                  */
711                 if (check_function_bodies)
712                 {
713                         set_items = (ArrayType *) DatumGetPointer(proconfig);
714                         if (set_items)          /* Need a new GUC nesting level */
715                         {
716                                 save_nestlevel = NewGUCNestLevel();
717                                 ProcessGUCArray(set_items,
718                                                                 (superuser() ? PGC_SUSET : PGC_USERSET),
719                                                                 PGC_S_SESSION,
720                                                                 GUC_ACTION_SAVE);
721                         }
722                 }
723
724                 OidFunctionCall1(languageValidator, ObjectIdGetDatum(retval));
725
726                 if (set_items)
727                         AtEOXact_GUC(true, save_nestlevel);
728         }
729
730         return myself;
731 }
732
733
734
735 /*
736  * Validator for internal functions
737  *
738  * Check that the given internal function name (the "prosrc" value) is
739  * a known builtin function.
740  */
741 Datum
742 fmgr_internal_validator(PG_FUNCTION_ARGS)
743 {
744         Oid                     funcoid = PG_GETARG_OID(0);
745         HeapTuple       tuple;
746         bool            isnull;
747         Datum           tmp;
748         char       *prosrc;
749
750         if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
751                 PG_RETURN_VOID();
752
753         /*
754          * We do not honor check_function_bodies since it's unlikely the function
755          * name will be found later if it isn't there now.
756          */
757
758         tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
759         if (!HeapTupleIsValid(tuple))
760                 elog(ERROR, "cache lookup failed for function %u", funcoid);
761
762         tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
763         if (isnull)
764                 elog(ERROR, "null prosrc");
765         prosrc = TextDatumGetCString(tmp);
766
767         if (fmgr_internal_function(prosrc) == InvalidOid)
768                 ereport(ERROR,
769                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
770                                  errmsg("there is no built-in function named \"%s\"",
771                                                 prosrc)));
772
773         ReleaseSysCache(tuple);
774
775         PG_RETURN_VOID();
776 }
777
778
779
780 /*
781  * Validator for C language functions
782  *
783  * Make sure that the library file exists, is loadable, and contains
784  * the specified link symbol. Also check for a valid function
785  * information record.
786  */
787 Datum
788 fmgr_c_validator(PG_FUNCTION_ARGS)
789 {
790         Oid                     funcoid = PG_GETARG_OID(0);
791         void       *libraryhandle;
792         HeapTuple       tuple;
793         bool            isnull;
794         Datum           tmp;
795         char       *prosrc;
796         char       *probin;
797
798         if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
799                 PG_RETURN_VOID();
800
801         /*
802          * It'd be most consistent to skip the check if !check_function_bodies,
803          * but the purpose of that switch is to be helpful for pg_dump loading,
804          * and for pg_dump loading it's much better if we *do* check.
805          */
806
807         tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
808         if (!HeapTupleIsValid(tuple))
809                 elog(ERROR, "cache lookup failed for function %u", funcoid);
810
811         tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
812         if (isnull)
813                 elog(ERROR, "null prosrc for C function %u", funcoid);
814         prosrc = TextDatumGetCString(tmp);
815
816         tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull);
817         if (isnull)
818                 elog(ERROR, "null probin for C function %u", funcoid);
819         probin = TextDatumGetCString(tmp);
820
821         (void) load_external_function(probin, prosrc, true, &libraryhandle);
822         (void) fetch_finfo_record(libraryhandle, prosrc);
823
824         ReleaseSysCache(tuple);
825
826         PG_RETURN_VOID();
827 }
828
829
830 /*
831  * Validator for SQL language functions
832  *
833  * Parse it here in order to be sure that it contains no syntax errors.
834  */
835 Datum
836 fmgr_sql_validator(PG_FUNCTION_ARGS)
837 {
838         Oid                     funcoid = PG_GETARG_OID(0);
839         HeapTuple       tuple;
840         Form_pg_proc proc;
841         List       *raw_parsetree_list;
842         List       *querytree_list;
843         ListCell   *lc;
844         bool            isnull;
845         Datum           tmp;
846         char       *prosrc;
847         parse_error_callback_arg callback_arg;
848         ErrorContextCallback sqlerrcontext;
849         bool            haspolyarg;
850         int                     i;
851
852         if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
853                 PG_RETURN_VOID();
854
855         tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
856         if (!HeapTupleIsValid(tuple))
857                 elog(ERROR, "cache lookup failed for function %u", funcoid);
858         proc = (Form_pg_proc) GETSTRUCT(tuple);
859
860         /* Disallow pseudotype result */
861         /* except for RECORD, VOID, or polymorphic */
862         if (get_typtype(proc->prorettype) == TYPTYPE_PSEUDO &&
863                 proc->prorettype != RECORDOID &&
864                 proc->prorettype != VOIDOID &&
865                 !IsPolymorphicType(proc->prorettype))
866                 ereport(ERROR,
867                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
868                                  errmsg("SQL functions cannot return type %s",
869                                                 format_type_be(proc->prorettype))));
870
871         /* Disallow pseudotypes in arguments */
872         /* except for polymorphic */
873         haspolyarg = false;
874         for (i = 0; i < proc->pronargs; i++)
875         {
876                 if (get_typtype(proc->proargtypes.values[i]) == TYPTYPE_PSEUDO)
877                 {
878                         if (IsPolymorphicType(proc->proargtypes.values[i]))
879                                 haspolyarg = true;
880                         else
881                                 ereport(ERROR,
882                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
883                                                  errmsg("SQL functions cannot have arguments of type %s",
884                                                                 format_type_be(proc->proargtypes.values[i]))));
885                 }
886         }
887
888         /* Postpone body checks if !check_function_bodies */
889         if (check_function_bodies)
890         {
891                 tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
892                 if (isnull)
893                         elog(ERROR, "null prosrc");
894
895                 prosrc = TextDatumGetCString(tmp);
896
897                 /*
898                  * Setup error traceback support for ereport().
899                  */
900                 callback_arg.proname = NameStr(proc->proname);
901                 callback_arg.prosrc = prosrc;
902
903                 sqlerrcontext.callback = sql_function_parse_error_callback;
904                 sqlerrcontext.arg = (void *) &callback_arg;
905                 sqlerrcontext.previous = error_context_stack;
906                 error_context_stack = &sqlerrcontext;
907
908                 /*
909                  * We can't do full prechecking of the function definition if there
910                  * are any polymorphic input types, because actual datatypes of
911                  * expression results will be unresolvable.  The check will be done at
912                  * runtime instead.
913                  *
914                  * We can run the text through the raw parser though; this will at
915                  * least catch silly syntactic errors.
916                  */
917                 raw_parsetree_list = pg_parse_query(prosrc);
918
919                 if (!haspolyarg)
920                 {
921                         /*
922                          * OK to do full precheck: analyze and rewrite the queries, then
923                          * verify the result type.
924                          */
925                         SQLFunctionParseInfoPtr pinfo;
926
927                         /* But first, set up parameter information */
928                         pinfo = prepare_sql_fn_parse_info(tuple, NULL, InvalidOid);
929
930                         querytree_list = NIL;
931                         foreach(lc, raw_parsetree_list)
932                         {
933                                 RawStmt    *parsetree = lfirst_node(RawStmt, lc);
934                                 List       *querytree_sublist;
935
936                                 querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
937                                                                                                                                   prosrc,
938                                                                                                                                   (ParserSetupHook) sql_fn_parser_setup,
939                                                                                                                                   pinfo,
940                                                                                                                                   NULL);
941                                 querytree_list = list_concat(querytree_list,
942                                                                                          querytree_sublist);
943                         }
944
945                         check_sql_fn_statements(querytree_list);
946                         (void) check_sql_fn_retval(funcoid, proc->prorettype,
947                                                                            querytree_list,
948                                                                            NULL, NULL);
949                 }
950
951                 error_context_stack = sqlerrcontext.previous;
952         }
953
954         ReleaseSysCache(tuple);
955
956         PG_RETURN_VOID();
957 }
958
959 /*
960  * Error context callback for handling errors in SQL function definitions
961  */
962 static void
963 sql_function_parse_error_callback(void *arg)
964 {
965         parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg;
966
967         /* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
968         if (!function_parse_error_transpose(callback_arg->prosrc))
969         {
970                 /* If it's not a syntax error, push info onto context stack */
971                 errcontext("SQL function \"%s\"", callback_arg->proname);
972         }
973 }
974
975 /*
976  * Adjust a syntax error occurring inside the function body of a CREATE
977  * FUNCTION or DO command.  This can be used by any function validator or
978  * anonymous-block handler, not only for SQL-language functions.
979  * It is assumed that the syntax error position is initially relative to the
980  * function body string (as passed in).  If possible, we adjust the position
981  * to reference the original command text; if we can't manage that, we set
982  * up an "internal query" syntax error instead.
983  *
984  * Returns true if a syntax error was processed, false if not.
985  */
986 bool
987 function_parse_error_transpose(const char *prosrc)
988 {
989         int                     origerrposition;
990         int                     newerrposition;
991         const char *queryText;
992
993         /*
994          * Nothing to do unless we are dealing with a syntax error that has a
995          * cursor position.
996          *
997          * Some PLs may prefer to report the error position as an internal error
998          * to begin with, so check that too.
999          */
1000         origerrposition = geterrposition();
1001         if (origerrposition <= 0)
1002         {
1003                 origerrposition = getinternalerrposition();
1004                 if (origerrposition <= 0)
1005                         return false;
1006         }
1007
1008         /* We can get the original query text from the active portal (hack...) */
1009         Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE);
1010         queryText = ActivePortal->sourceText;
1011
1012         /* Try to locate the prosrc in the original text */
1013         newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition);
1014
1015         if (newerrposition > 0)
1016         {
1017                 /* Successful, so fix error position to reference original query */
1018                 errposition(newerrposition);
1019                 /* Get rid of any report of the error as an "internal query" */
1020                 internalerrposition(0);
1021                 internalerrquery(NULL);
1022         }
1023         else
1024         {
1025                 /*
1026                  * If unsuccessful, convert the position to an internal position
1027                  * marker and give the function text as the internal query.
1028                  */
1029                 errposition(0);
1030                 internalerrposition(origerrposition);
1031                 internalerrquery(prosrc);
1032         }
1033
1034         return true;
1035 }
1036
1037 /*
1038  * Try to locate the string literal containing the function body in the
1039  * given text of the CREATE FUNCTION or DO command.  If successful, return
1040  * the character (not byte) index within the command corresponding to the
1041  * given character index within the literal.  If not successful, return 0.
1042  */
1043 static int
1044 match_prosrc_to_query(const char *prosrc, const char *queryText,
1045                                           int cursorpos)
1046 {
1047         /*
1048          * Rather than fully parsing the original command, we just scan the
1049          * command looking for $prosrc$ or 'prosrc'.  This could be fooled (though
1050          * not in any very probable scenarios), so fail if we find more than one
1051          * match.
1052          */
1053         int                     prosrclen = strlen(prosrc);
1054         int                     querylen = strlen(queryText);
1055         int                     matchpos = 0;
1056         int                     curpos;
1057         int                     newcursorpos;
1058
1059         for (curpos = 0; curpos < querylen - prosrclen; curpos++)
1060         {
1061                 if (queryText[curpos] == '$' &&
1062                         strncmp(prosrc, &queryText[curpos + 1], prosrclen) == 0 &&
1063                         queryText[curpos + 1 + prosrclen] == '$')
1064                 {
1065                         /*
1066                          * Found a $foo$ match.  Since there are no embedded quoting
1067                          * characters in a dollar-quoted literal, we don't have to do any
1068                          * fancy arithmetic; just offset by the starting position.
1069                          */
1070                         if (matchpos)
1071                                 return 0;               /* multiple matches, fail */
1072                         matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
1073                                 + cursorpos;
1074                 }
1075                 else if (queryText[curpos] == '\'' &&
1076                                  match_prosrc_to_literal(prosrc, &queryText[curpos + 1],
1077                                                                                  cursorpos, &newcursorpos))
1078                 {
1079                         /*
1080                          * Found a 'foo' match.  match_prosrc_to_literal() has adjusted
1081                          * for any quotes or backslashes embedded in the literal.
1082                          */
1083                         if (matchpos)
1084                                 return 0;               /* multiple matches, fail */
1085                         matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
1086                                 + newcursorpos;
1087                 }
1088         }
1089
1090         return matchpos;
1091 }
1092
1093 /*
1094  * Try to match the given source text to a single-quoted literal.
1095  * If successful, adjust newcursorpos to correspond to the character
1096  * (not byte) index corresponding to cursorpos in the source text.
1097  *
1098  * At entry, literal points just past a ' character.  We must check for the
1099  * trailing quote.
1100  */
1101 static bool
1102 match_prosrc_to_literal(const char *prosrc, const char *literal,
1103                                                 int cursorpos, int *newcursorpos)
1104 {
1105         int                     newcp = cursorpos;
1106         int                     chlen;
1107
1108         /*
1109          * This implementation handles backslashes and doubled quotes in the
1110          * string literal.  It does not handle the SQL syntax for literals
1111          * continued across line boundaries.
1112          *
1113          * We do the comparison a character at a time, not a byte at a time, so
1114          * that we can do the correct cursorpos math.
1115          */
1116         while (*prosrc)
1117         {
1118                 cursorpos--;                    /* characters left before cursor */
1119
1120                 /*
1121                  * Check for backslashes and doubled quotes in the literal; adjust
1122                  * newcp when one is found before the cursor.
1123                  */
1124                 if (*literal == '\\')
1125                 {
1126                         literal++;
1127                         if (cursorpos > 0)
1128                                 newcp++;
1129                 }
1130                 else if (*literal == '\'')
1131                 {
1132                         if (literal[1] != '\'')
1133                                 goto fail;
1134                         literal++;
1135                         if (cursorpos > 0)
1136                                 newcp++;
1137                 }
1138                 chlen = pg_mblen(prosrc);
1139                 if (strncmp(prosrc, literal, chlen) != 0)
1140                         goto fail;
1141                 prosrc += chlen;
1142                 literal += chlen;
1143         }
1144
1145         if (*literal == '\'' && literal[1] != '\'')
1146         {
1147                 /* success */
1148                 *newcursorpos = newcp;
1149                 return true;
1150         }
1151
1152 fail:
1153         /* Must set *newcursorpos to suppress compiler warning */
1154         *newcursorpos = newcp;
1155         return false;
1156 }
1157
1158 List *
1159 oid_array_to_list(Datum datum)
1160 {
1161         ArrayType  *array = DatumGetArrayTypeP(datum);
1162         Datum      *values;
1163         int                     nelems;
1164         int                     i;
1165         List       *result = NIL;
1166
1167         deconstruct_array(array,
1168                                           OIDOID,
1169                                           sizeof(Oid), true, 'i',
1170                                           &values, NULL, &nelems);
1171         for (i = 0; i < nelems; i++)
1172                 result = lappend_oid(result, values[i]);
1173         return result;
1174 }