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