PostgreSQL Source Code: src/backend/commands/functioncmds.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
34
74
75
76
77
78
79
80
81
82
83
84
85
86
87static void
89 Oid *prorettype_p, bool *returnsSet_p)
90{
91 Oid rettype;
94
95 typtup = LookupTypeName(NULL, returnType, NULL, false);
96
97 if (typtup)
98 {
100 {
101 if (languageOid == SQLlanguageId)
103 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
104 errmsg("SQL function cannot return shell type %s",
106 else
108 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
109 errmsg("return type %s is only a shell",
111 }
114 }
115 else
116 {
118 Oid namespaceId;
121
122
123
124
125
126
127
128 if (languageOid != INTERNALlanguageId &&
129 languageOid != ClanguageId)
131 (errcode(ERRCODE_UNDEFINED_OBJECT),
132 errmsg("type \"%s\" does not exist", typnam)));
133
134
137 (errcode(ERRCODE_SYNTAX_ERROR),
138 errmsg("type modifier cannot be specified for shell type \"%s\"",
139 typnam)));
140
141
143 (errcode(ERRCODE_UNDEFINED_OBJECT),
144 errmsg("type \"%s\" is not yet defined", typnam),
145 errdetail("Creating a shell type definition.")));
156 }
157
161
162 *prorettype_p = rettype;
163 *returnsSet_p = returnType->setof;
164}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182void
184 List *parameters,
185 Oid languageOid,
188 List **parameterTypes_list,
192 List **inParameterNames_list,
193 List **parameterDefaults,
194 Oid *variadicArgType,
195 Oid *requiredResultType)
196{
197 int parameterCount = list_length(parameters);
198 Oid *inTypes;
199 int inCount = 0;
201 Datum *paramModes;
202 Datum *paramNames;
203 int outCount = 0;
204 int varCount = 0;
205 bool have_names = false;
206 bool have_defaults = false;
208 int i;
209
210 *variadicArgType = InvalidOid;
211 *requiredResultType = InvalidOid;
212
213 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
215 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
217 *parameterDefaults = NIL;
218
219
220 i = 0;
221 foreach(x, parameters)
222 {
226 bool isinput = false;
227 Oid toid;
230
231
234
236 if (typtup)
237 {
239 {
240
241 if (languageOid == SQLlanguageId)
243 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
244 errmsg("SQL function cannot accept shell type %s",
247
250 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
251 errmsg("aggregate cannot accept shell type %s",
254 else
256 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
257 errmsg("argument type %s is only a shell",
260 }
263 }
264 else
265 {
267 (errcode(ERRCODE_UNDEFINED_OBJECT),
268 errmsg("type %s does not exist",
271 toid = InvalidOid;
272 }
273
277
279 {
282 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
283 errmsg("aggregates cannot accept set arguments"),
287 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
288 errmsg("procedures cannot accept set arguments"),
290 else
292 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
293 errmsg("functions cannot accept set arguments"),
295 }
296
297
299 {
300
301 if (varCount > 0)
303 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
304 errmsg("VARIADIC parameter must be the last input parameter"),
306 inTypes[inCount++] = toid;
307 isinput = true;
308 if (parameterTypes_list)
309 *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
310 }
311
312
314 {
316 {
317
318
319
320
321
322 if (varCount > 0)
324 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
325 errmsg("VARIADIC parameter must be the last parameter"),
327
328 *requiredResultType = RECORDOID;
329 }
330 else if (outCount == 0)
331 *requiredResultType = toid;
332 outCount++;
333 }
334
336 {
337 *variadicArgType = toid;
338 varCount++;
339
340 switch (toid)
341 {
342 case ANYARRAYOID:
343 case ANYCOMPATIBLEARRAYOID:
344 case ANYOID:
345
346 break;
347 default:
350 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
351 errmsg("VARIADIC parameter must be an array"),
353 break;
354 }
355 }
356
358
360
362 {
364
365
366
367
368
369
370
371 foreach(px, parameters)
372 {
375
376 if (prevfp == fp)
377 break;
378
379 prevfpmode = prevfp->mode;
382
387 continue;
392 continue;
393 if (prevfp->name && prevfp->name[0] &&
394 strcmp(prevfp->name, fp->name) == 0)
396 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
397 errmsg("parameter name \"%s\" used more than once",
400 }
401
403 have_names = true;
404 }
405
406 if (inParameterNames_list)
408
410 {
412
413 if (!isinput)
415 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
416 errmsg("only input parameters can have default values"),
418
423
424
425
426
427
431 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
432 errmsg("cannot use table references in parameter default value"),
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 *parameterDefaults = lappend(*parameterDefaults, def);
450 have_defaults = true;
451 }
452 else
453 {
454 if (isinput && have_defaults)
456 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
457 errmsg("input parameters after one with a default value must also have defaults"),
459
460
461
462
463
464
467 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
468 errmsg("procedure OUT parameters cannot appear after one with a default value"),
470 }
471
472 i++;
473 }
474
475
477
478 if (outCount > 0 || varCount > 0)
479 {
482 if (outCount > 1)
483 *requiredResultType = RECORDOID;
484
485 }
486 else
487 {
488 *allParameterTypes = NULL;
489 *parameterModes = NULL;
490 }
491
492 if (have_names)
493 {
494 for (i = 0; i < parameterCount; i++)
495 {
498 }
500 }
501 else
502 *parameterNames = NULL;
503}
504
505
506
507
508
509
510
511
512
513
514static bool
516 bool is_procedure,
518 DefElem **volatility_item,
521 DefElem **leakproof_item,
522 List **set_items,
527{
528 if (strcmp(defel->defname, "volatility") == 0)
529 {
530 if (is_procedure)
531 goto procedure_error;
532 if (*volatility_item)
534
535 *volatility_item = defel;
536 }
537 else if (strcmp(defel->defname, "strict") == 0)
538 {
539 if (is_procedure)
540 goto procedure_error;
541 if (*strict_item)
543
544 *strict_item = defel;
545 }
546 else if (strcmp(defel->defname, "security") == 0)
547 {
548 if (*security_item)
550
551 *security_item = defel;
552 }
553 else if (strcmp(defel->defname, "leakproof") == 0)
554 {
555 if (is_procedure)
556 goto procedure_error;
557 if (*leakproof_item)
559
560 *leakproof_item = defel;
561 }
562 else if (strcmp(defel->defname, "set") == 0)
563 {
564 *set_items = lappend(*set_items, defel->arg);
565 }
566 else if (strcmp(defel->defname, "cost") == 0)
567 {
568 if (is_procedure)
569 goto procedure_error;
570 if (*cost_item)
572
573 *cost_item = defel;
574 }
575 else if (strcmp(defel->defname, "rows") == 0)
576 {
577 if (is_procedure)
578 goto procedure_error;
579 if (*rows_item)
581
582 *rows_item = defel;
583 }
584 else if (strcmp(defel->defname, "support") == 0)
585 {
586 if (is_procedure)
587 goto procedure_error;
588 if (*support_item)
590
591 *support_item = defel;
592 }
593 else if (strcmp(defel->defname, "parallel") == 0)
594 {
595 if (is_procedure)
596 goto procedure_error;
597 if (*parallel_item)
599
600 *parallel_item = defel;
601 }
602 else
603 return false;
604
605
606 return true;
607
608procedure_error:
610 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
611 errmsg("invalid attribute in procedure definition"),
613 return false;
614}
615
616static char
618{
620
621 if (strcmp(str, "immutable") == 0)
622 return PROVOLATILE_IMMUTABLE;
623 else if (strcmp(str, "stable") == 0)
624 return PROVOLATILE_STABLE;
625 else if (strcmp(str, "volatile") == 0)
626 return PROVOLATILE_VOLATILE;
627 else
628 {
629 elog(ERROR, "invalid volatility \"%s\"", str);
630 return 0;
631 }
632}
633
634static char
636{
638
639 if (strcmp(str, "safe") == 0)
640 return PROPARALLEL_SAFE;
641 else if (strcmp(str, "unsafe") == 0)
642 return PROPARALLEL_UNSAFE;
643 else if (strcmp(str, "restricted") == 0)
644 return PROPARALLEL_RESTRICTED;
645 else
646 {
648 (errcode(ERRCODE_SYNTAX_ERROR),
649 errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
650 return PROPARALLEL_UNSAFE;
651 }
652}
653
654
655
656
657
658
661{
663
664 foreach(l, set_items)
665 {
667
669 a = NULL;
670 else
671 {
673
674 if (valuestr)
676 else
678 }
679 }
680
681 return a;
682}
683
684static Oid
686{
688 Oid procOid;
689 Oid argList[1];
690
691
692
693
694
695 argList[0] = INTERNALOID;
696
697 procOid = LookupFuncName(procName, 1, argList, true);
700 (errcode(ERRCODE_UNDEFINED_FUNCTION),
701 errmsg("function %s does not exist",
703
706 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
707 errmsg("support function %s must return type %s",
709
710
711
712
713
714
717 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
718 errmsg("must be superuser to specify a support function")));
719
720 return procOid;
721}
722
723
724
725
726
727
728static void
730 bool is_procedure,
733 char **language,
734 Node **transform,
735 bool *windowfunc_p,
736 char *volatility_p,
737 bool *strict_p,
738 bool *security_definer,
739 bool *leakproof_p,
743 Oid *prosupport,
744 char *parallel_p)
745{
748 DefElem *language_item = NULL;
749 DefElem *transform_item = NULL;
750 DefElem *windowfunc_item = NULL;
751 DefElem *volatility_item = NULL;
752 DefElem *strict_item = NULL;
753 DefElem *security_item = NULL;
754 DefElem *leakproof_item = NULL;
756 DefElem *cost_item = NULL;
757 DefElem *rows_item = NULL;
758 DefElem *support_item = NULL;
759 DefElem *parallel_item = NULL;
760
762 {
764
765 if (strcmp(defel->defname, "as") == 0)
766 {
767 if (as_item)
769 as_item = defel;
770 }
771 else if (strcmp(defel->defname, "language") == 0)
772 {
773 if (language_item)
775 language_item = defel;
776 }
777 else if (strcmp(defel->defname, "transform") == 0)
778 {
779 if (transform_item)
781 transform_item = defel;
782 }
783 else if (strcmp(defel->defname, "window") == 0)
784 {
785 if (windowfunc_item)
787 if (is_procedure)
789 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
790 errmsg("invalid attribute in procedure definition"),
792 windowfunc_item = defel;
793 }
795 is_procedure,
796 defel,
797 &volatility_item,
798 &strict_item,
799 &security_item,
800 &leakproof_item,
801 &set_items,
802 &cost_item,
803 &rows_item,
804 &support_item,
805 ¶llel_item))
806 {
807
808 continue;
809 }
810 else
811 elog(ERROR, "option \"%s\" not recognized",
813 }
814
815 if (as_item)
816 *as = (List *) as_item->arg;
817 if (language_item)
818 *language = strVal(language_item->arg);
819 if (transform_item)
820 *transform = transform_item->arg;
821 if (windowfunc_item)
822 *windowfunc_p = boolVal(windowfunc_item->arg);
823 if (volatility_item)
825 if (strict_item)
826 *strict_p = boolVal(strict_item->arg);
827 if (security_item)
828 *security_definer = boolVal(security_item->arg);
829 if (leakproof_item)
830 *leakproof_p = boolVal(leakproof_item->arg);
831 if (set_items)
833 if (cost_item)
834 {
836 if (*procost <= 0)
838 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
839 errmsg("COST must be positive")));
840 }
841 if (rows_item)
842 {
844 if (*prorows <= 0)
846 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
847 errmsg("ROWS must be positive")));
848 }
849 if (support_item)
851 if (parallel_item)
853}
854
855
856
857
858
859
860
861
862
863
864
865static void
868 List *parameterTypes, List *inParameterNames,
869 char **prosrc_str_p, char **probin_str_p,
870 Node **sql_body_out,
871 const char *queryString)
872{
873 if (!sql_body_in && !as)
875 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
876 errmsg("no function body specified")));
877
878 if (sql_body_in && as)
880 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
881 errmsg("duplicate function body specified")));
882
883 if (sql_body_in && languageOid != SQLlanguageId)
885 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
886 errmsg("inline SQL function body only valid for language SQL")));
887
888 *sql_body_out = NULL;
889
890 if (languageOid == ClanguageId)
891 {
892
893
894
895
896
897
898
899
903 else
904 {
906 if (strcmp(*prosrc_str_p, "-") == 0)
908 }
909 }
910 else if (sql_body_in)
911 {
913
915
920 for (int i = 0; i < list_length(parameterTypes); i++)
921 {
923
925 if (IsPolymorphicType(pinfo->argtypes[i]))
927 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
928 errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
929
930 if (s[0] != '\0')
932 else
934 }
935
936 if (IsA(sql_body_in, List))
937 {
940 List *transformed_stmts = NIL;
941
942 foreach(lc, stmts)
943 {
947
953 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
954 errmsg("%s is not yet supported in unquoted SQL function body",
956 transformed_stmts = lappend(transformed_stmts, q);
958 }
959
960 *sql_body_out = (Node *) list_make1(transformed_stmts);
961 }
962 else
963 {
966
972 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
973 errmsg("%s is not yet supported in unquoted SQL function body",
976
977 *sql_body_out = (Node *) q;
978 }
979
980
981
982
983
984
985
986
987 *prosrc_str_p = pstrdup("");
988
989
990 *probin_str_p = NULL;
991 }
992 else
993 {
994
996 *probin_str_p = NULL;
997
1000 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1001 errmsg("only one AS item needed for language \"%s\"",
1002 languageName)));
1003
1004 if (languageOid == INTERNALlanguageId)
1005 {
1006
1007
1008
1009
1010
1011
1012
1013
1014 if (strlen(*prosrc_str_p) == 0)
1016 }
1017 }
1018}
1019
1020
1021
1022
1023
1024
1027{
1028 char *probin_str;
1029 char *prosrc_str;
1030 Node *prosqlbody;
1031 Oid prorettype;
1032 bool returnsSet;
1033 char *language;
1034 Oid languageOid;
1035 Oid languageValidator;
1036 Node *transformDefElem = NULL;
1038 Oid namespaceId;
1041 List *parameterTypes_list = NIL;
1045 List *inParameterNames_list = NIL;
1046 List *parameterDefaults;
1047 Oid variadicArgType;
1048 List *trftypes_list = NIL;
1049 List *trfoids_list = NIL;
1051 Oid requiredResultType;
1052 bool isWindowFunc,
1053 isStrict,
1054 security,
1055 isLeakProof;
1056 char volatility;
1060 Oid prosupport;
1063 List *as_clause;
1064 char parallel;
1065
1066
1069
1070
1075
1076
1077 as_clause = NIL;
1078 language = NULL;
1079 isWindowFunc = false;
1080 isStrict = false;
1081 security = false;
1082 isLeakProof = false;
1083 volatility = PROVOLATILE_VOLATILE;
1084 proconfig = NULL;
1085 procost = -1;
1086 prorows = -1;
1088 parallel = PROPARALLEL_UNSAFE;
1089
1090
1092 stmt->is_procedure,
1093 stmt->options,
1094 &as_clause, &language, &transformDefElem,
1095 &isWindowFunc, &volatility,
1096 &isStrict, &security, &isLeakProof,
1097 &proconfig, &procost, &prorows,
1098 &prosupport, ¶llel);
1099
1100 if (!language)
1101 {
1102 if (stmt->sql_body)
1103 language = "sql";
1104 else
1106 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1107 errmsg("no language specified")));
1108 }
1109
1110
1114 (errcode(ERRCODE_UNDEFINED_OBJECT),
1115 errmsg("language \"%s\" does not exist", language),
1117 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1118
1120 languageOid = languageStruct->oid;
1121
1122 if (languageStruct->lanpltrusted)
1123 {
1124
1128 NameStr(languageStruct->lanname));
1129 }
1130 else
1131 {
1132
1135 NameStr(languageStruct->lanname));
1136 }
1137
1138 languageValidator = languageStruct->lanvalidator;
1139
1141
1142
1143
1144
1145
1146
1147 if (isLeakProof && ())
1149 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1150 errmsg("only superuser can define a leakproof function")));
1151
1152 if (transformDefElem)
1153 {
1155
1156 foreach(lc, castNode(List, transformDefElem))
1157 {
1161 Oid transformid;
1162
1163 typeid = elt ? elt : typeid;
1165 trftypes_list = lappend_oid(trftypes_list, typeid);
1166 trfoids_list = lappend_oid(trfoids_list, transformid);
1167 }
1168 }
1169
1170
1171
1172
1173
1175 stmt->parameters,
1176 languageOid,
1178 ¶meterTypes,
1179 ¶meterTypes_list,
1180 &allParameterTypes,
1181 ¶meterModes,
1182 ¶meterNames,
1183 &inParameterNames_list,
1184 ¶meterDefaults,
1185 &variadicArgType,
1186 &requiredResultType);
1187
1188 if (stmt->is_procedure)
1189 {
1191 prorettype = requiredResultType ? requiredResultType : VOIDOID;
1192 returnsSet = false;
1193 }
1194 else if (stmt->returnType)
1195 {
1196
1198 &prorettype, &returnsSet);
1199 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1201 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1202 errmsg("function result type must be %s because of OUT parameters",
1204 }
1205 else if (OidIsValid(requiredResultType))
1206 {
1207
1208 prorettype = requiredResultType;
1209 returnsSet = false;
1210 }
1211 else
1212 {
1214 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1215 errmsg("function result type must be specified")));
1216
1217 prorettype = VOIDOID;
1218 returnsSet = false;
1219 }
1220
1221 if (trftypes_list != NIL)
1222 {
1225 int i;
1226
1228 i = 0;
1229 foreach(lc, trftypes_list)
1232 }
1233 else
1234 {
1235
1236 trftypes = NULL;
1237 }
1238
1240 parameterTypes_list, inParameterNames_list,
1241 &prosrc_str, &probin_str, &prosqlbody,
1243
1244
1245
1246
1247
1248
1249 if (procost < 0)
1250 {
1251
1252 if (languageOid == INTERNALlanguageId ||
1253 languageOid == ClanguageId)
1254 procost = 1;
1255 else
1256 procost = 100;
1257 }
1258 if (prorows < 0)
1259 {
1260 if (returnsSet)
1261 prorows = 1000;
1262 else
1263 prorows = 0;
1264 }
1265 else if (!returnsSet)
1267 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1268 errmsg("ROWS is not applicable when function does not return a set")));
1269
1270
1271
1272
1273
1275 namespaceId,
1276 stmt->replace,
1277 returnsSet,
1278 prorettype,
1280 languageOid,
1281 languageValidator,
1282 prosrc_str,
1283 probin_str,
1284 prosqlbody,
1285 stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1286 security,
1287 isLeakProof,
1288 isStrict,
1289 volatility,
1290 parallel,
1291 parameterTypes,
1295 parameterDefaults,
1297 trfoids_list,
1299 prosupport,
1300 procost,
1301 prorows);
1302}
1303
1304
1305
1306
1307
1308
1309
1310void
1312{
1315 char prokind;
1316
1317
1318
1319
1321
1324 elog(ERROR, "cache lookup failed for function %u", funcOid);
1325
1327
1329
1331
1333
1335
1336
1337
1338
1339 if (prokind == PROKIND_AGGREGATE)
1340 {
1342
1345 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1346
1348
1350
1352 }
1353}
1354
1355
1356
1357
1358
1359
1362{
1364 Oid funcOid;
1366 bool is_procedure;
1369 DefElem *volatility_item = NULL;
1370 DefElem *strict_item = NULL;
1371 DefElem *security_def_item = NULL;
1372 DefElem *leakproof_item = NULL;
1374 DefElem *cost_item = NULL;
1375 DefElem *rows_item = NULL;
1376 DefElem *support_item = NULL;
1377 DefElem *parallel_item = NULL;
1379
1381
1383
1385
1388 elog(ERROR, "cache lookup failed for function %u", funcOid);
1389
1391
1392
1396
1397 if (procForm->prokind == PROKIND_AGGREGATE)
1399 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1400 errmsg("\"%s\" is an aggregate function",
1402
1403 is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1404
1405
1406 foreach(l, stmt->actions)
1407 {
1409
1411 is_procedure,
1412 defel,
1413 &volatility_item,
1414 &strict_item,
1415 &security_def_item,
1416 &leakproof_item,
1417 &set_items,
1418 &cost_item,
1419 &rows_item,
1420 &support_item,
1421 ¶llel_item) == false)
1422 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1423 }
1424
1425 if (volatility_item)
1427 if (strict_item)
1428 procForm->proisstrict = boolVal(strict_item->arg);
1429 if (security_def_item)
1430 procForm->prosecdef = boolVal(security_def_item->arg);
1431 if (leakproof_item)
1432 {
1433 procForm->proleakproof = boolVal(leakproof_item->arg);
1434 if (procForm->proleakproof && ())
1436 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1437 errmsg("only superuser can define a leakproof function")));
1438 }
1439 if (cost_item)
1440 {
1442 if (procForm->procost <= 0)
1444 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1445 errmsg("COST must be positive")));
1446 }
1447 if (rows_item)
1448 {
1450 if (procForm->prorows <= 0)
1452 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1453 errmsg("ROWS must be positive")));
1454 if (!procForm->proretset)
1456 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1457 errmsg("ROWS is not applicable when function does not return a set")));
1458 }
1459 if (support_item)
1460 {
1461
1463
1464
1465 if (OidIsValid(procForm->prosupport))
1466 {
1468 ProcedureRelationId, procForm->prosupport,
1469 newsupport) != 1)
1470 elog(ERROR, "could not change support dependency for function %s",
1472 }
1473 else
1474 {
1476
1477 referenced.classId = ProcedureRelationId;
1478 referenced.objectId = newsupport;
1481 }
1482
1483 procForm->prosupport = newsupport;
1484 }
1485 if (parallel_item)
1487 if (set_items)
1488 {
1490 bool isnull;
1492 Datum repl_val[Natts_pg_proc];
1493 bool repl_null[Natts_pg_proc];
1494 bool repl_repl[Natts_pg_proc];
1495
1496
1497 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1499
1500
1502
1503
1504 memset(repl_repl, false, sizeof(repl_repl));
1505 repl_repl[Anum_pg_proc_proconfig - 1] = true;
1506
1507 if (a == NULL)
1508 {
1509 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1510 repl_null[Anum_pg_proc_proconfig - 1] = true;
1511 }
1512 else
1513 {
1515 repl_null[Anum_pg_proc_proconfig - 1] = false;
1516 }
1517
1519 repl_val, repl_null, repl_repl);
1520 }
1521
1522
1523
1525
1527
1530
1531 return address;
1532}
1533
1534
1535
1536
1537
1540{
1541 Oid sourcetypeid;
1542 Oid targettypeid;
1543 char sourcetyptype;
1544 char targettyptype;
1545 Oid funcid;
1548 int nargs;
1549 char castcontext;
1550 char castmethod;
1554
1557 sourcetyptype = get_typtype(sourcetypeid);
1558 targettyptype = get_typtype(targettypeid);
1559
1560
1561 if (sourcetyptype == TYPTYPE_PSEUDO)
1563 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1564 errmsg("source data type %s is a pseudo-type",
1566
1567 if (targettyptype == TYPTYPE_PSEUDO)
1569 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1570 errmsg("target data type %s is a pseudo-type",
1572
1573
1577 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1578 errmsg("must be owner of type %s or type %s",
1581
1585
1589
1590
1591 if (sourcetyptype == TYPTYPE_DOMAIN)
1593 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1594 errmsg("cast will be ignored because the source data type is a domain")));
1595
1596 else if (targettyptype == TYPTYPE_DOMAIN)
1598 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1599 errmsg("cast will be ignored because the target data type is a domain")));
1600
1601
1602 if (stmt->func != NULL)
1603 castmethod = COERCION_METHOD_FUNCTION;
1604 else if (stmt->inout)
1605 castmethod = COERCION_METHOD_INOUT;
1606 else
1607 castmethod = COERCION_METHOD_BINARY;
1608
1609 if (castmethod == COERCION_METHOD_FUNCTION)
1610 {
1612
1614
1617 elog(ERROR, "cache lookup failed for function %u", funcid);
1618
1620 nargs = procstruct->pronargs;
1621 if (nargs < 1 || nargs > 3)
1623 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1624 errmsg("cast function must take one to three arguments")));
1626 procstruct->proargtypes.values[0],
1627 &incastid))
1629 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1630 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1631 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1633 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1634 errmsg("second argument of cast function must be type %s",
1635 "integer")));
1636 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1638 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1639 errmsg("third argument of cast function must be type %s",
1640 "boolean")));
1642 targettypeid,
1643 &outcastid))
1645 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1646 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1647
1648
1649
1650
1651
1652
1653#ifdef NOT_USED
1654 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1656 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1657 errmsg("cast function must not be volatile")));
1658#endif
1659 if (procstruct->prokind != PROKIND_FUNCTION)
1661 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1662 errmsg("cast function must be a normal function")));
1663 if (procstruct->proretset)
1665 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1666 errmsg("cast function must not return a set")));
1667
1669 }
1670 else
1671 {
1673 nargs = 0;
1674 }
1675
1676 if (castmethod == COERCION_METHOD_BINARY)
1677 {
1680 bool typ1byval;
1681 bool typ2byval;
1682 char typ1align;
1683 char typ2align;
1684
1685
1686
1687
1688
1691 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1692 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1693
1694
1695
1696
1697
1698
1699
1702 if (typ1len != typ2len ||
1703 typ1byval != typ2byval ||
1704 typ1align != typ2align)
1706 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1707 errmsg("source and target data types are not physically compatible")));
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723 if (sourcetyptype == TYPTYPE_COMPOSITE ||
1724 targettyptype == TYPTYPE_COMPOSITE)
1726 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1727 errmsg("composite data types are not binary-compatible")));
1728
1732 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1733 errmsg("array data types are not binary-compatible")));
1734
1735 if (sourcetyptype == TYPTYPE_RANGE ||
1736 targettyptype == TYPTYPE_RANGE ||
1737 sourcetyptype == TYPTYPE_MULTIRANGE ||
1738 targettyptype == TYPTYPE_MULTIRANGE)
1740 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1741 errmsg("range data types are not binary-compatible")));
1742
1743 if (sourcetyptype == TYPTYPE_ENUM ||
1744 targettyptype == TYPTYPE_ENUM)
1746 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1747 errmsg("enum data types are not binary-compatible")));
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760 if (sourcetyptype == TYPTYPE_DOMAIN ||
1761 targettyptype == TYPTYPE_DOMAIN)
1763 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1764 errmsg("domain data types must not be marked binary-compatible")));
1765 }
1766
1767
1768
1769
1770
1771 if (sourcetypeid == targettypeid && nargs < 2)
1773 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1774 errmsg("source data type and target data type are the same")));
1775
1776
1777 switch (stmt->context)
1778 {
1780 castcontext = COERCION_CODE_IMPLICIT;
1781 break;
1783 castcontext = COERCION_CODE_ASSIGNMENT;
1784 break;
1785
1787 castcontext = COERCION_CODE_EXPLICIT;
1788 break;
1789 default:
1790 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1791 castcontext = 0;
1792 break;
1793 }
1794
1795 myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1797 return myself;
1798}
1799
1800
1801static void
1803{
1804 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1806 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1807 errmsg("transform function must not be volatile")));
1808 if (procstruct->prokind != PROKIND_FUNCTION)
1810 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1811 errmsg("transform function must be a normal function")));
1812 if (procstruct->proretset)
1814 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1815 errmsg("transform function must not return a set")));
1816 if (procstruct->pronargs != 1)
1818 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1819 errmsg("transform function must take one argument")));
1820 if (procstruct->proargtypes.values[0] != INTERNALOID)
1822 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1823 errmsg("first argument of transform function must be type %s",
1824 "internal")));
1825}
1826
1827
1828
1829
1830
1833{
1834 Oid typeid;
1835 char typtype;
1836 Oid langid;
1837 Oid fromsqlfuncid;
1838 Oid tosqlfuncid;
1842 bool nulls[Natts_pg_transform] = {0};
1843 bool replaces[Natts_pg_transform] = {0};
1844 Oid transformid;
1849 referenced;
1851 bool is_replace;
1852
1853
1854
1855
1858
1859 if (typtype == TYPTYPE_PSEUDO)
1861 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1862 errmsg("data type %s is a pseudo-type",
1864
1865 if (typtype == TYPTYPE_DOMAIN)
1867 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1868 errmsg("data type %s is a domain",
1870
1873
1877
1878
1879
1880
1882
1886
1887
1888
1889
1890 if (stmt->fromsql)
1891 {
1893
1896
1900
1903 elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1905 if (procstruct->prorettype != INTERNALOID)
1907 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1908 errmsg("return data type of FROM SQL function must be %s",
1909 "internal")));
1912 }
1913 else
1915
1916 if (stmt->tosql)
1917 {
1919
1922
1926
1929 elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1931 if (procstruct->prorettype != typeid)
1933 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1934 errmsg("return data type of TO SQL function must be the transform data type")));
1937 }
1938 else
1940
1941
1942
1943
1948
1950
1955 {
1957
1958 if (->replace)
1961 errmsg("transform for type %s language \"%s\" already exists",
1963 stmt->lang)));
1964
1965 replaces[Anum_pg_transform_trffromsql - 1] = true;
1966 replaces[Anum_pg_transform_trftosql - 1] = true;
1967
1970
1971 transformid = form->oid;
1973 is_replace = true;
1974 }
1975 else
1976 {
1978 Anum_pg_transform_oid);
1982 is_replace = false;
1983 }
1984
1985 if (is_replace)
1987
1989
1990
1992
1993
1996
1997
2000
2001
2003 {
2004 ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
2006 }
2008 {
2009 ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
2011 }
2012
2015
2016
2018
2019
2021
2023
2025
2026 return myself;
2027}
2028
2029
2030
2031
2032
2033
2034
2035
2038{
2039 Oid oid;
2040
2041 oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2044 if ((oid) && !missing_ok)
2046 (errcode(ERRCODE_UNDEFINED_OBJECT),
2047 errmsg("transform for type %s language \"%s\" does not exist",
2050 return oid;
2051}
2052
2053
2054
2055
2056
2057
2058
2059
2060void
2063{
2064
2070 (errcode(ERRCODE_DUPLICATE_FUNCTION),
2071 errmsg("function %s already exists in schema \"%s\"",
2075}
2076
2077
2078
2079
2080
2081
2082
2083void
2085{
2088 DefElem *as_item = NULL;
2089 DefElem *language_item = NULL;
2090 char *language;
2091 Oid laninline;
2094
2095
2097 {
2099
2100 if (strcmp(defel->defname, "as") == 0)
2101 {
2102 if (as_item)
2104 as_item = defel;
2105 }
2106 else if (strcmp(defel->defname, "language") == 0)
2107 {
2108 if (language_item)
2110 language_item = defel;
2111 }
2112 else
2113 elog(ERROR, "option \"%s\" not recognized",
2115 }
2116
2117 if (as_item)
2119 else
2121 (errcode(ERRCODE_SYNTAX_ERROR),
2122 errmsg("no inline code specified")));
2123
2124
2125 if (language_item)
2126 language = strVal(language_item->arg);
2127 else
2128 language = "plpgsql";
2129
2130
2134 (errcode(ERRCODE_UNDEFINED_OBJECT),
2135 errmsg("language \"%s\" does not exist", language),
2137 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2138
2140 codeblock->langOid = languageStruct->oid;
2141 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2142 codeblock->atomic = atomic;
2143
2144 if (languageStruct->lanpltrusted)
2145 {
2146
2148
2153 NameStr(languageStruct->lanname));
2154 }
2155 else
2156 {
2157
2160 NameStr(languageStruct->lanname));
2161 }
2162
2163
2164 laninline = languageStruct->laninline;
2167 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2168 errmsg("language \"%s\" does not support inline code execution",
2169 NameStr(languageStruct->lanname))));
2170
2172
2173
2175}
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205void
2207{
2211 int nargs;
2212 int i;
2221
2222 fexpr = stmt->funcexpr;
2225
2229
2230
2232 callcontext->atomic = atomic;
2233
2236 elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2237
2238
2239
2240
2241
2242
2243
2244 if ((tp, Anum_pg_proc_proconfig, NULL))
2245 callcontext->atomic = true;
2246
2247
2248
2249
2250
2251
2252
2254 callcontext->atomic = true;
2255
2257
2258
2262 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2263 errmsg_plural("cannot pass more than %d argument to a procedure",
2264 "cannot pass more than %d arguments to a procedure",
2267
2268
2273 (Node *) callcontext, NULL);
2274
2275
2276
2277
2278
2282
2283
2284
2285
2286
2287
2288
2289
2290 if (!atomic)
2292
2293 i = 0;
2294 foreach(lc, fexpr->args)
2295 {
2298 bool isnull;
2299
2301
2303
2304 fcinfo->args[i].value = val;
2305 fcinfo->args[i].isnull = isnull;
2306
2307 i++;
2308 }
2309
2310
2311 if (!atomic)
2313
2314
2318
2319
2320 if (fexpr->funcresulttype == VOIDOID)
2321 {
2322
2323 }
2324 else if (fexpr->funcresulttype == RECORDOID)
2325 {
2326
2328 Oid tupType;
2329 int32 tupTypmod;
2334
2335 if (fcinfo->isnull)
2336 elog(ERROR, "procedure returned null record");
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2351
2356
2359
2363 rettupdata.t_data = td;
2364
2367
2369
2371 }
2372 else
2373 elog(ERROR, "unexpected result type for procedure: %u",
2374 fexpr->funcresulttype);
2375
2377}
2378
2379
2380
2381
2384{
2388
2389 fexpr = stmt->funcexpr;
2390
2393 elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2394
2396
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409 if (tupdesc)
2410 {
2412 for (int i = 0; i < tupdesc->natts; i++)
2413 {
2416
2418 i + 1,
2421 -1,
2422 0);
2423 }
2424 }
2425
2426 return tupdesc;
2427}
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
#define DatumGetArrayTypeP(X)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
const char * GetCommandTagName(CommandTag commandTag)
List * defGetQualifiedName(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
double defGetNumeric(DefElem *def)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
void end_tup_output(TupOutputState *tstate)
const TupleTableSlotOps TTSOpsHeapTuple
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
ExprContext * CreateExprContext(EState *estate)
void FreeExecutorState(EState *estate)
EState * CreateExecutorState(void)
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
bool extension_file_exists(const char *extensionName)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
#define OidFunctionCall1(functionId, arg1)
#define DatumGetHeapTupleHeader(X)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
#define LOCAL_FCINFO(name, nargs)
#define FunctionCallInvoke(fcinfo)
#define fmgr_info_set_expr(expr, finfo)
char * format_type_be(Oid type_oid)
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
ObjectAddress CreateCast(CreateCastStmt *stmt)
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
static Oid interpret_func_support(DefElem *defel)
static void compute_function_attributes(ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
static bool compute_common_attribute(ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
static char interpret_func_volatility(DefElem *defel)
ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
void IsThereFunctionInNamespace(const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
ObjectAddress AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
TupleDesc CallStmtResultDesc(CallStmt *stmt)
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
static void check_transform_function(Form_pg_proc procstruct)
ObjectAddress CreateTransform(CreateTransformStmt *stmt)
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
void RemoveFunctionById(Oid funcOid)
static char interpret_func_parallel(DefElem *defel)
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static void * GETSTRUCT(const HeapTupleData *tuple)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
if(TABLE==NULL||TABLE_index==NULL)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
Oid get_element_type(Oid typid)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
char * get_language_name(Oid langoid, bool missing_ok)
char * get_func_name(Oid funcid)
char get_typtype(Oid typid)
Oid get_base_element_type(Oid typid)
char * get_namespace_name(Oid nspid)
Oid get_func_rettype(Oid funcid)
char * pstrdup(const char *in)
void * palloc0(Size size)
char * NameListToString(const List *names)
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Oid exprType(const Node *expr)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeFunctionExecuteHook(objectId)
#define ObjectAddressSet(addr, class_id, object_id)
oidvector * buildoidvector(const Oid *oids, int n)
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
bool IsBinaryCoercibleWithCast(Oid srctype, Oid targettype, Oid *castoid)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
void free_parsestate(ParseState *pstate)
int parser_errposition(ParseState *pstate, int location)
ParseState * make_parsestate(ParseState *parentParseState)
@ EXPR_KIND_FUNCTION_DEFAULT
char * TypeNameToString(const TypeName *typeName)
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Query * transformStmt(ParseState *pstate, Node *parseTree)
FormData_pg_attribute * Form_pg_attribute
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, Oid incastid, Oid outcastid, char castcontext, char castmethod, DependencyType behavior)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
FormData_pg_language * Form_pg_language
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
static Oid list_nth_oid(const List *list, int n)
static void * list_nth(const List *list, int n)
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, Node *prosqlbody, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, List *trfoids, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
FormData_pg_proc * Form_pg_proc
FormData_pg_transform * Form_pg_transform
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
FormData_pg_type * Form_pg_type
void pgstat_drop_function(Oid proid)
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Datum CStringGetDatum(const char *X)
static Datum CharGetDatum(char X)
void EnsurePortalSnapshotExists(void)
Oid get_language_oid(const char *langname, bool missing_ok)
#define RelationGetDescr(relation)
Snapshot GetTransactionSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void PopActiveSnapshot(void)
#define ERRCODE_DUPLICATE_OBJECT
ParamListInfo es_param_list_info
FunctionParameterMode mode
const char * p_sourcetext
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Oid values[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
#define SearchSysCacheCopy1(cacheId, key1)
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
#define ReleaseTupleDesc(tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
CommandTag CreateCommandTag(Node *parsetree)
String * makeString(char *str)
bool contain_var_clause(Node *node)