PostgreSQL Source Code  git master
functioncmds.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_proc_fn.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type_fn.h"
#include "commands/alter.h"
#include "commands/defrem.h"
#include "commands/proclang.h"
#include "executor/execdesc.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "optimizer/var.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for functioncmds.c:

Go to the source code of this file.

Functions

static void compute_return_type (TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
 
void interpret_function_parameter_list (ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, 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 **parallel_item)
 
static char interpret_func_volatility (DefElem *defel)
 
static char interpret_func_parallel (DefElem *defel)
 
static ArrayTypeupdate_proconfig_value (ArrayType *a, List *set_items)
 
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, char *parallel_p)
 
static void interpret_AS_clause (Oid languageOid, const char *languageName, char *funcname, List *as, char **prosrc_str_p, char **probin_str_p)
 
ObjectAddress CreateFunction (ParseState *pstate, CreateFunctionStmt *stmt)
 
void RemoveFunctionById (Oid funcOid)
 
ObjectAddress AlterFunction (ParseState *pstate, AlterFunctionStmt *stmt)
 
void SetFunctionReturnType (Oid funcOid, Oid newRetType)
 
void SetFunctionArgType (Oid funcOid, int argIndex, Oid newArgType)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
Oid get_cast_oid (Oid sourcetypeid, Oid targettypeid, bool missing_ok)
 
void DropCastById (Oid castOid)
 
static void check_transform_function (Form_pg_proc procstruct)
 
ObjectAddress CreateTransform (CreateTransformStmt *stmt)
 
Oid get_transform_oid (Oid type_id, Oid lang_id, bool missing_ok)
 
void DropTransformById (Oid transformOid)
 
void IsThereFunctionInNamespace (const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
 
void ExecuteDoStmt (DoStmt *stmt, bool atomic)
 
void ExecuteCallStmt (ParseState *pstate, CallStmt *stmt, bool atomic)
 

Function Documentation

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1173 of file functioncmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, AlterFunctionStmt::actions, Anum_pg_proc_proconfig, DefElem::arg, CatalogTupleUpdate(), compute_common_attribute(), DatumGetArrayTypeP, defGetNumeric(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, AlterFunctionStmt::func, GETSTRUCT, GetUserId(), heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, interpret_func_parallel(), interpret_func_volatility(), intVal, InvalidOid, InvokeObjectPostAlterHook, lfirst, LookupFuncWithArgs(), NameListToString(), Natts_pg_proc, NIL, NoLock, ObjectAddressSet, ObjectIdGetDatum, ObjectWithArgs::objname, AlterFunctionStmt::objtype, pg_proc_ownercheck(), PointerGetDatum, ProcedureRelationId, PROCOID, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, and update_proconfig_value().

Referenced by ProcessUtilitySlow().

1174 {
1175  HeapTuple tup;
1176  Oid funcOid;
1177  Form_pg_proc procForm;
1178  bool is_procedure;
1179  Relation rel;
1180  ListCell *l;
1181  DefElem *volatility_item = NULL;
1182  DefElem *strict_item = NULL;
1183  DefElem *security_def_item = NULL;
1184  DefElem *leakproof_item = NULL;
1185  List *set_items = NIL;
1186  DefElem *cost_item = NULL;
1187  DefElem *rows_item = NULL;
1188  DefElem *parallel_item = NULL;
1189  ObjectAddress address;
1190 
1192 
1193  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1194 
1195  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1196  if (!HeapTupleIsValid(tup)) /* should not happen */
1197  elog(ERROR, "cache lookup failed for function %u", funcOid);
1198 
1199  procForm = (Form_pg_proc) GETSTRUCT(tup);
1200 
1201  /* Permission check: must own function */
1202  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1204  NameListToString(stmt->func->objname));
1205 
1206  if (procForm->proisagg)
1207  ereport(ERROR,
1208  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1209  errmsg("\"%s\" is an aggregate function",
1210  NameListToString(stmt->func->objname))));
1211 
1212  is_procedure = (procForm->prorettype == InvalidOid);
1213 
1214  /* Examine requested actions. */
1215  foreach(l, stmt->actions)
1216  {
1217  DefElem *defel = (DefElem *) lfirst(l);
1218 
1219  if (compute_common_attribute(pstate,
1220  is_procedure,
1221  defel,
1222  &volatility_item,
1223  &strict_item,
1224  &security_def_item,
1225  &leakproof_item,
1226  &set_items,
1227  &cost_item,
1228  &rows_item,
1229  &parallel_item) == false)
1230  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1231  }
1232 
1233  if (volatility_item)
1234  procForm->provolatile = interpret_func_volatility(volatility_item);
1235  if (strict_item)
1236  procForm->proisstrict = intVal(strict_item->arg);
1237  if (security_def_item)
1238  procForm->prosecdef = intVal(security_def_item->arg);
1239  if (leakproof_item)
1240  {
1241  procForm->proleakproof = intVal(leakproof_item->arg);
1242  if (procForm->proleakproof && !superuser())
1243  ereport(ERROR,
1244  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1245  errmsg("only superuser can define a leakproof function")));
1246  }
1247  if (cost_item)
1248  {
1249  procForm->procost = defGetNumeric(cost_item);
1250  if (procForm->procost <= 0)
1251  ereport(ERROR,
1252  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1253  errmsg("COST must be positive")));
1254  }
1255  if (rows_item)
1256  {
1257  procForm->prorows = defGetNumeric(rows_item);
1258  if (procForm->prorows <= 0)
1259  ereport(ERROR,
1260  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1261  errmsg("ROWS must be positive")));
1262  if (!procForm->proretset)
1263  ereport(ERROR,
1264  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1265  errmsg("ROWS is not applicable when function does not return a set")));
1266  }
1267  if (set_items)
1268  {
1269  Datum datum;
1270  bool isnull;
1271  ArrayType *a;
1272  Datum repl_val[Natts_pg_proc];
1273  bool repl_null[Natts_pg_proc];
1274  bool repl_repl[Natts_pg_proc];
1275 
1276  /* extract existing proconfig setting */
1277  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1278  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1279 
1280  /* update according to each SET or RESET item, left to right */
1281  a = update_proconfig_value(a, set_items);
1282 
1283  /* update the tuple */
1284  memset(repl_repl, false, sizeof(repl_repl));
1285  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1286 
1287  if (a == NULL)
1288  {
1289  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1290  repl_null[Anum_pg_proc_proconfig - 1] = true;
1291  }
1292  else
1293  {
1294  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1295  repl_null[Anum_pg_proc_proconfig - 1] = false;
1296  }
1297 
1298  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1299  repl_val, repl_null, repl_repl);
1300  }
1301  if (parallel_item)
1302  procForm->proparallel = interpret_func_parallel(parallel_item);
1303 
1304  /* Do the update */
1305  CatalogTupleUpdate(rel, &tup->t_self, tup);
1306 
1308 
1309  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1310 
1311  heap_close(rel, NoLock);
1312  heap_freetuple(tup);
1313 
1314  return address;
1315 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
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 **parallel_item)
Definition: functioncmds.c:468
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:539
#define ProcedureRelationId
Definition: pg_proc.h:33
double defGetNumeric(DefElem *def)
Definition: define.c:85
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_proc_proconfig
Definition: pg_proc.h:117
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define Natts_pg_proc
Definition: pg_proc.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2784
#define NoLock
Definition: lockdefs.h:34
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2028
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:567
Node * arg
Definition: parsenodes.h:728
char * NameListToString(List *names)
Definition: namespace.c:3063
uintptr_t Datum
Definition: postgres.h:365
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:610
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * func
Definition: parsenodes.h:2785
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:727
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4830
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:585
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1774 of file functioncmds.c.

References ereport, errcode(), errmsg(), ERROR, INTERNALOID, and PROVOLATILE_VOLATILE.

Referenced by CreateTransform().

1775 {
1776  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1779  errmsg("transform function must not be volatile")));
1780  if (procstruct->proisagg)
1781  ereport(ERROR,
1782  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1783  errmsg("transform function must not be an aggregate function")));
1784  if (procstruct->proiswindow)
1785  ereport(ERROR,
1786  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1787  errmsg("transform function must not be a window function")));
1788  if (procstruct->proretset)
1789  ereport(ERROR,
1790  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1791  errmsg("transform function must not return a set")));
1792  if (procstruct->pronargs != 1)
1793  ereport(ERROR,
1794  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1795  errmsg("transform function must take one argument")));
1796  if (procstruct->proargtypes.values[0] != INTERNALOID)
1797  ereport(ERROR,
1798  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1799  errmsg("first argument of transform function must be type %s",
1800  "internal")));
1801 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5574
#define INTERNALOID
Definition: pg_type.h:698
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ compute_common_attribute()

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 **  parallel_item 
)
static

Definition at line 468 of file functioncmds.c.

References DefElem::arg, DefElem::defname, ereport, errcode(), errmsg(), ERROR, lappend(), DefElem::location, and parser_errposition().

Referenced by AlterFunction(), and compute_function_attributes().

479 {
480  if (strcmp(defel->defname, "volatility") == 0)
481  {
482  if (is_procedure)
483  goto procedure_error;
484  if (*volatility_item)
485  goto duplicate_error;
486 
487  *volatility_item = defel;
488  }
489  else if (strcmp(defel->defname, "strict") == 0)
490  {
491  if (is_procedure)
492  goto procedure_error;
493  if (*strict_item)
494  goto duplicate_error;
495 
496  *strict_item = defel;
497  }
498  else if (strcmp(defel->defname, "security") == 0)
499  {
500  if (*security_item)
501  goto duplicate_error;
502 
503  *security_item = defel;
504  }
505  else if (strcmp(defel->defname, "leakproof") == 0)
506  {
507  if (is_procedure)
508  goto procedure_error;
509  if (*leakproof_item)
510  goto duplicate_error;
511 
512  *leakproof_item = defel;
513  }
514  else if (strcmp(defel->defname, "set") == 0)
515  {
516  *set_items = lappend(*set_items, defel->arg);
517  }
518  else if (strcmp(defel->defname, "cost") == 0)
519  {
520  if (is_procedure)
521  goto procedure_error;
522  if (*cost_item)
523  goto duplicate_error;
524 
525  *cost_item = defel;
526  }
527  else if (strcmp(defel->defname, "rows") == 0)
528  {
529  if (is_procedure)
530  goto procedure_error;
531  if (*rows_item)
532  goto duplicate_error;
533 
534  *rows_item = defel;
535  }
536  else if (strcmp(defel->defname, "parallel") == 0)
537  {
538  if (is_procedure)
539  goto procedure_error;
540  if (*parallel_item)
541  goto duplicate_error;
542 
543  *parallel_item = defel;
544  }
545  else
546  return false;
547 
548  /* Recognized an option */
549  return true;
550 
551 duplicate_error:
552  ereport(ERROR,
553  (errcode(ERRCODE_SYNTAX_ERROR),
554  errmsg("conflicting or redundant options"),
555  parser_errposition(pstate, defel->location)));
556  return false; /* keep compiler quiet */
557 
558 procedure_error:
559  ereport(ERROR,
560  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
561  errmsg("invalid attribute in procedure definition"),
562  parser_errposition(pstate, defel->location)));
563  return false;
564 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
int location
Definition: parsenodes.h:730
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:728
List * lappend(List *list, void *datum)
Definition: list.c:128
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:727

◆ compute_function_attributes()

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,
char *  parallel_p 
)
static

Definition at line 640 of file functioncmds.c.

References DefElem::arg, compute_common_attribute(), defGetNumeric(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, interpret_func_parallel(), interpret_func_volatility(), intVal, lfirst, DefElem::location, NIL, parser_errposition(), strVal, and update_proconfig_value().

Referenced by CreateFunction().

655 {
656  ListCell *option;
657  DefElem *as_item = NULL;
658  DefElem *language_item = NULL;
659  DefElem *transform_item = NULL;
660  DefElem *windowfunc_item = NULL;
661  DefElem *volatility_item = NULL;
662  DefElem *strict_item = NULL;
663  DefElem *security_item = NULL;
664  DefElem *leakproof_item = NULL;
665  List *set_items = NIL;
666  DefElem *cost_item = NULL;
667  DefElem *rows_item = NULL;
668  DefElem *parallel_item = NULL;
669 
670  foreach(option, options)
671  {
672  DefElem *defel = (DefElem *) lfirst(option);
673 
674  if (strcmp(defel->defname, "as") == 0)
675  {
676  if (as_item)
677  ereport(ERROR,
678  (errcode(ERRCODE_SYNTAX_ERROR),
679  errmsg("conflicting or redundant options"),
680  parser_errposition(pstate, defel->location)));
681  as_item = defel;
682  }
683  else if (strcmp(defel->defname, "language") == 0)
684  {
685  if (language_item)
686  ereport(ERROR,
687  (errcode(ERRCODE_SYNTAX_ERROR),
688  errmsg("conflicting or redundant options"),
689  parser_errposition(pstate, defel->location)));
690  language_item = defel;
691  }
692  else if (strcmp(defel->defname, "transform") == 0)
693  {
694  if (transform_item)
695  ereport(ERROR,
696  (errcode(ERRCODE_SYNTAX_ERROR),
697  errmsg("conflicting or redundant options"),
698  parser_errposition(pstate, defel->location)));
699  transform_item = defel;
700  }
701  else if (strcmp(defel->defname, "window") == 0)
702  {
703  if (windowfunc_item)
704  ereport(ERROR,
705  (errcode(ERRCODE_SYNTAX_ERROR),
706  errmsg("conflicting or redundant options"),
707  parser_errposition(pstate, defel->location)));
708  if (is_procedure)
709  ereport(ERROR,
710  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
711  errmsg("invalid attribute in procedure definition"),
712  parser_errposition(pstate, defel->location)));
713  windowfunc_item = defel;
714  }
715  else if (compute_common_attribute(pstate,
716  is_procedure,
717  defel,
718  &volatility_item,
719  &strict_item,
720  &security_item,
721  &leakproof_item,
722  &set_items,
723  &cost_item,
724  &rows_item,
725  &parallel_item))
726  {
727  /* recognized common option */
728  continue;
729  }
730  else
731  elog(ERROR, "option \"%s\" not recognized",
732  defel->defname);
733  }
734 
735  /* process required items */
736  if (as_item)
737  *as = (List *) as_item->arg;
738  else
739  {
740  ereport(ERROR,
741  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
742  errmsg("no function body specified")));
743  *as = NIL; /* keep compiler quiet */
744  }
745 
746  if (language_item)
747  *language = strVal(language_item->arg);
748  else
749  {
750  ereport(ERROR,
751  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
752  errmsg("no language specified")));
753  *language = NULL; /* keep compiler quiet */
754  }
755 
756  /* process optional items */
757  if (transform_item)
758  *transform = transform_item->arg;
759  if (windowfunc_item)
760  *windowfunc_p = intVal(windowfunc_item->arg);
761  if (volatility_item)
762  *volatility_p = interpret_func_volatility(volatility_item);
763  if (strict_item)
764  *strict_p = intVal(strict_item->arg);
765  if (security_item)
766  *security_definer = intVal(security_item->arg);
767  if (leakproof_item)
768  *leakproof_p = intVal(leakproof_item->arg);
769  if (set_items)
770  *proconfig = update_proconfig_value(NULL, set_items);
771  if (cost_item)
772  {
773  *procost = defGetNumeric(cost_item);
774  if (*procost <= 0)
775  ereport(ERROR,
776  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
777  errmsg("COST must be positive")));
778  }
779  if (rows_item)
780  {
781  *prorows = defGetNumeric(rows_item);
782  if (*prorows <= 0)
783  ereport(ERROR,
784  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
785  errmsg("ROWS must be positive")));
786  }
787  if (parallel_item)
788  *parallel_p = interpret_func_parallel(parallel_item);
789 }
#define NIL
Definition: pg_list.h:69
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 **parallel_item)
Definition: functioncmds.c:468
double defGetNumeric(DefElem *def)
Definition: define.c:85
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
int location
Definition: parsenodes.h:730
#define ereport(elevel, rest)
Definition: elog.h:122
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:567
Node * arg
Definition: parsenodes.h:728
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:610
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:727
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:585

◆ compute_return_type()

static void compute_return_type ( TypeName returnType,
Oid  languageOid,
Oid prorettype_p,
bool returnsSet_p 
)
static

Definition at line 86 of file functioncmds.c.

References ACL_CREATE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, Assert, ClanguageId, ereport, errcode(), errdetail(), errmsg(), ERROR, get_namespace_name(), GETSTRUCT, GetUserId(), INTERNALlanguageId, LookupTypeName(), TypeName::names, NIL, NOTICE, OBJECT_SCHEMA, ObjectAddress::objectId, OidIsValid, pg_namespace_aclcheck(), pg_type_aclcheck(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, SQLlanguageId, TypeNameToString(), TypeShellMake(), typeTypeId(), and TypeName::typmods.

Referenced by CreateFunction().

88 {
89  Oid rettype;
90  Type typtup;
91  AclResult aclresult;
92 
93  typtup = LookupTypeName(NULL, returnType, NULL, false);
94 
95  if (typtup)
96  {
97  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
98  {
99  if (languageOid == SQLlanguageId)
100  ereport(ERROR,
101  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
102  errmsg("SQL function cannot return shell type %s",
103  TypeNameToString(returnType))));
104  else
105  ereport(NOTICE,
106  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
107  errmsg("return type %s is only a shell",
108  TypeNameToString(returnType))));
109  }
110  rettype = typeTypeId(typtup);
111  ReleaseSysCache(typtup);
112  }
113  else
114  {
115  char *typnam = TypeNameToString(returnType);
116  Oid namespaceId;
117  AclResult aclresult;
118  char *typname;
119  ObjectAddress address;
120 
121  /*
122  * Only C-coded functions can be I/O functions. We enforce this
123  * restriction here mainly to prevent littering the catalogs with
124  * shell types due to simple typos in user-defined function
125  * definitions.
126  */
127  if (languageOid != INTERNALlanguageId &&
128  languageOid != ClanguageId)
129  ereport(ERROR,
130  (errcode(ERRCODE_UNDEFINED_OBJECT),
131  errmsg("type \"%s\" does not exist", typnam)));
132 
133  /* Reject if there's typmod decoration, too */
134  if (returnType->typmods != NIL)
135  ereport(ERROR,
136  (errcode(ERRCODE_SYNTAX_ERROR),
137  errmsg("type modifier cannot be specified for shell type \"%s\"",
138  typnam)));
139 
140  /* Otherwise, go ahead and make a shell type */
141  ereport(NOTICE,
142  (errcode(ERRCODE_UNDEFINED_OBJECT),
143  errmsg("type \"%s\" is not yet defined", typnam),
144  errdetail("Creating a shell type definition.")));
145  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
146  &typname);
147  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
148  ACL_CREATE);
149  if (aclresult != ACLCHECK_OK)
150  aclcheck_error(aclresult, OBJECT_SCHEMA,
151  get_namespace_name(namespaceId));
152  address = TypeShellMake(typname, namespaceId, GetUserId());
153  rettype = address.objectId;
154  Assert(OidIsValid(rettype));
155  }
156 
157  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
158  if (aclresult != ACLCHECK_OK)
159  aclcheck_error_type(aclresult, rettype);
160 
161  *prorettype_p = rettype;
162  *returnsSet_p = returnType->setof;
163 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
List * names
Definition: parsenodes.h:208
#define INTERNALlanguageId
Definition: pg_language.h:74
Oid GetUserId(void)
Definition: miscinit.c:284
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define ClanguageId
Definition: pg_language.h:77
int errcode(int sqlerrcode)
Definition: elog.c:575
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:56
#define OidIsValid(objectId)
Definition: c.h:594
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4690
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3663
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define SQLlanguageId
Definition: pg_language.h:80
bool setof
Definition: parsenodes.h:210
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
List * typmods
Definition: parsenodes.h:212
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:688
int errmsg(const char *fmt,...)
Definition: elog.c:797
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4740
Oid typeTypeId(Type tp)
Definition: parse_type.c:571

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1409 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, Anum_pg_cast_castcontext, Anum_pg_cast_castfunc, Anum_pg_cast_castmethod, Anum_pg_cast_castsource, Anum_pg_cast_casttarget, BOOLOID, CastRelationId, CASTSOURCETARGET, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, COERCION_ASSIGNMENT, COERCION_CODE_ASSIGNMENT, COERCION_CODE_EXPLICIT, COERCION_CODE_IMPLICIT, COERCION_EXPLICIT, COERCION_IMPLICIT, COERCION_METHOD_BINARY, COERCION_METHOD_FUNCTION, COERCION_METHOD_INOUT, CreateCastStmt::context, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), CreateCastStmt::func, get_element_type(), get_typlenbyvalalign(), get_typtype(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleIsValid, CreateCastStmt::inout, INT4OID, InvalidOid, InvokeObjectPostCreateHook, IsBinaryCoercible(), LookupFuncWithArgs(), MemSet, Natts_pg_cast, OBJECT_FUNCTION, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_type_aclcheck(), pg_type_ownercheck(), ProcedureRelationId, PROCOID, PROVOLATILE_VOLATILE, recordDependencyOn(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), CreateCastStmt::sourcetype, superuser(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), TypeRelationId, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, TYPTYPE_ENUM, TYPTYPE_PSEUDO, values, and WARNING.

Referenced by ProcessUtilitySlow().

1410 {
1411  Oid sourcetypeid;
1412  Oid targettypeid;
1413  char sourcetyptype;
1414  char targettyptype;
1415  Oid funcid;
1416  Oid castid;
1417  int nargs;
1418  char castcontext;
1419  char castmethod;
1420  Relation relation;
1421  HeapTuple tuple;
1423  bool nulls[Natts_pg_cast];
1424  ObjectAddress myself,
1425  referenced;
1426  AclResult aclresult;
1427 
1428  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1429  targettypeid = typenameTypeId(NULL, stmt->targettype);
1430  sourcetyptype = get_typtype(sourcetypeid);
1431  targettyptype = get_typtype(targettypeid);
1432 
1433  /* No pseudo-types allowed */
1434  if (sourcetyptype == TYPTYPE_PSEUDO)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1437  errmsg("source data type %s is a pseudo-type",
1438  TypeNameToString(stmt->sourcetype))));
1439 
1440  if (targettyptype == TYPTYPE_PSEUDO)
1441  ereport(ERROR,
1442  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1443  errmsg("target data type %s is a pseudo-type",
1444  TypeNameToString(stmt->targettype))));
1445 
1446  /* Permission check */
1447  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1448  && !pg_type_ownercheck(targettypeid, GetUserId()))
1449  ereport(ERROR,
1450  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1451  errmsg("must be owner of type %s or type %s",
1452  format_type_be(sourcetypeid),
1453  format_type_be(targettypeid))));
1454 
1455  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1456  if (aclresult != ACLCHECK_OK)
1457  aclcheck_error_type(aclresult, sourcetypeid);
1458 
1459  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1460  if (aclresult != ACLCHECK_OK)
1461  aclcheck_error_type(aclresult, targettypeid);
1462 
1463  /* Domains are allowed for historical reasons, but we warn */
1464  if (sourcetyptype == TYPTYPE_DOMAIN)
1465  ereport(WARNING,
1466  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1467  errmsg("cast will be ignored because the source data type is a domain")));
1468 
1469  else if (targettyptype == TYPTYPE_DOMAIN)
1470  ereport(WARNING,
1471  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1472  errmsg("cast will be ignored because the target data type is a domain")));
1473 
1474  /* Determine the cast method */
1475  if (stmt->func != NULL)
1476  castmethod = COERCION_METHOD_FUNCTION;
1477  else if (stmt->inout)
1478  castmethod = COERCION_METHOD_INOUT;
1479  else
1480  castmethod = COERCION_METHOD_BINARY;
1481 
1482  if (castmethod == COERCION_METHOD_FUNCTION)
1483  {
1484  Form_pg_proc procstruct;
1485 
1486  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1487 
1488  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1489  if (!HeapTupleIsValid(tuple))
1490  elog(ERROR, "cache lookup failed for function %u", funcid);
1491 
1492  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1493  nargs = procstruct->pronargs;
1494  if (nargs < 1 || nargs > 3)
1495  ereport(ERROR,
1496  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1497  errmsg("cast function must take one to three arguments")));
1498  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1499  ereport(ERROR,
1500  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1501  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1502  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1503  ereport(ERROR,
1504  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1505  errmsg("second argument of cast function must be type %s",
1506  "integer")));
1507  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1508  ereport(ERROR,
1509  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1510  errmsg("third argument of cast function must be type %s",
1511  "boolean")));
1512  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1513  ereport(ERROR,
1514  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1515  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1516 
1517  /*
1518  * Restricting the volatility of a cast function may or may not be a
1519  * good idea in the abstract, but it definitely breaks many old
1520  * user-defined types. Disable this check --- tgl 2/1/03
1521  */
1522 #ifdef NOT_USED
1523  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1524  ereport(ERROR,
1525  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1526  errmsg("cast function must not be volatile")));
1527 #endif
1528  if (procstruct->proisagg)
1529  ereport(ERROR,
1530  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1531  errmsg("cast function must not be an aggregate function")));
1532  if (procstruct->proiswindow)
1533  ereport(ERROR,
1534  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1535  errmsg("cast function must not be a window function")));
1536  if (procstruct->proretset)
1537  ereport(ERROR,
1538  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1539  errmsg("cast function must not return a set")));
1540 
1541  ReleaseSysCache(tuple);
1542  }
1543  else
1544  {
1545  funcid = InvalidOid;
1546  nargs = 0;
1547  }
1548 
1549  if (castmethod == COERCION_METHOD_BINARY)
1550  {
1551  int16 typ1len;
1552  int16 typ2len;
1553  bool typ1byval;
1554  bool typ2byval;
1555  char typ1align;
1556  char typ2align;
1557 
1558  /*
1559  * Must be superuser to create binary-compatible casts, since
1560  * erroneous casts can easily crash the backend.
1561  */
1562  if (!superuser())
1563  ereport(ERROR,
1564  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1565  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1566 
1567  /*
1568  * Also, insist that the types match as to size, alignment, and
1569  * pass-by-value attributes; this provides at least a crude check that
1570  * they have similar representations. A pair of types that fail this
1571  * test should certainly not be equated.
1572  */
1573  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1574  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1575  if (typ1len != typ2len ||
1576  typ1byval != typ2byval ||
1577  typ1align != typ2align)
1578  ereport(ERROR,
1579  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1580  errmsg("source and target data types are not physically compatible")));
1581 
1582  /*
1583  * We know that composite, enum and array types are never binary-
1584  * compatible with each other. They all have OIDs embedded in them.
1585  *
1586  * Theoretically you could build a user-defined base type that is
1587  * binary-compatible with a composite, enum, or array type. But we
1588  * disallow that too, as in practice such a cast is surely a mistake.
1589  * You can always work around that by writing a cast function.
1590  */
1591  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1592  targettyptype == TYPTYPE_COMPOSITE)
1593  ereport(ERROR,
1594  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1595  errmsg("composite data types are not binary-compatible")));
1596 
1597  if (sourcetyptype == TYPTYPE_ENUM ||
1598  targettyptype == TYPTYPE_ENUM)
1599  ereport(ERROR,
1600  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1601  errmsg("enum data types are not binary-compatible")));
1602 
1603  if (OidIsValid(get_element_type(sourcetypeid)) ||
1604  OidIsValid(get_element_type(targettypeid)))
1605  ereport(ERROR,
1606  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1607  errmsg("array data types are not binary-compatible")));
1608 
1609  /*
1610  * We also disallow creating binary-compatibility casts involving
1611  * domains. Casting from a domain to its base type is already
1612  * allowed, and casting the other way ought to go through domain
1613  * coercion to permit constraint checking. Again, if you're intent on
1614  * having your own semantics for that, create a no-op cast function.
1615  *
1616  * NOTE: if we were to relax this, the above checks for composites
1617  * etc. would have to be modified to look through domains to their
1618  * base types.
1619  */
1620  if (sourcetyptype == TYPTYPE_DOMAIN ||
1621  targettyptype == TYPTYPE_DOMAIN)
1622  ereport(ERROR,
1623  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1624  errmsg("domain data types must not be marked binary-compatible")));
1625  }
1626 
1627  /*
1628  * Allow source and target types to be same only for length coercion
1629  * functions. We assume a multi-arg function does length coercion.
1630  */
1631  if (sourcetypeid == targettypeid && nargs < 2)
1632  ereport(ERROR,
1633  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1634  errmsg("source data type and target data type are the same")));
1635 
1636  /* convert CoercionContext enum to char value for castcontext */
1637  switch (stmt->context)
1638  {
1639  case COERCION_IMPLICIT:
1640  castcontext = COERCION_CODE_IMPLICIT;
1641  break;
1642  case COERCION_ASSIGNMENT:
1643  castcontext = COERCION_CODE_ASSIGNMENT;
1644  break;
1645  case COERCION_EXPLICIT:
1646  castcontext = COERCION_CODE_EXPLICIT;
1647  break;
1648  default:
1649  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1650  castcontext = 0; /* keep compiler quiet */
1651  break;
1652  }
1653 
1655 
1656  /*
1657  * Check for duplicate. This is just to give a friendly error message,
1658  * the unique index would catch it anyway (so no need to sweat about race
1659  * conditions).
1660  */
1662  ObjectIdGetDatum(sourcetypeid),
1663  ObjectIdGetDatum(targettypeid));
1664  if (HeapTupleIsValid(tuple))
1665  ereport(ERROR,
1667  errmsg("cast from type %s to type %s already exists",
1668  format_type_be(sourcetypeid),
1669  format_type_be(targettypeid))));
1670 
1671  /* ready to go */
1672  values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1673  values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1674  values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1675  values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1676  values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1677 
1678  MemSet(nulls, false, sizeof(nulls));
1679 
1680  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1681 
1682  castid = CatalogTupleInsert(relation, tuple);
1683 
1684  /* make dependency entries */
1685  myself.classId = CastRelationId;
1686  myself.objectId = castid;
1687  myself.objectSubId = 0;
1688 
1689  /* dependency on source type */
1690  referenced.classId = TypeRelationId;
1691  referenced.objectId = sourcetypeid;
1692  referenced.objectSubId = 0;
1693  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1694 
1695  /* dependency on target type */
1696  referenced.classId = TypeRelationId;
1697  referenced.objectId = targettypeid;
1698  referenced.objectSubId = 0;
1699  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1700 
1701  /* dependency on function */
1702  if (OidIsValid(funcid))
1703  {
1704  referenced.classId = ProcedureRelationId;
1705  referenced.objectId = funcid;
1706  referenced.objectSubId = 0;
1707  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1708  }
1709 
1710  /* dependency on extension */
1711  recordDependencyOnCurrentExtension(&myself, false);
1712 
1713  /* Post creation hook for new cast */
1715 
1716  heap_freetuple(tuple);
1717 
1718  heap_close(relation, RowExclusiveLock);
1719 
1720  return myself;
1721 }
signed short int16
Definition: c.h:301
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
TypeName * sourcetype
Definition: parsenodes.h:3303
#define Anum_pg_cast_castfunc
Definition: pg_cast.h:80
#define Anum_pg_cast_casttarget
Definition: pg_cast.h:79
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2025
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define ProcedureRelationId
Definition: pg_proc.h:33
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2383
#define MemSet(start, val, len)
Definition: c.h:897
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4778
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:594
#define Anum_pg_cast_castmethod
Definition: pg_cast.h:82
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3663
#define Natts_pg_cast
Definition: pg_cast.h:77
#define Anum_pg_cast_castsource
Definition: pg_cast.h:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2028
CoercionContext context
Definition: parsenodes.h:3306
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5574
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
ObjectWithArgs * func
Definition: parsenodes.h:3305
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define CastRelationId
Definition: pg_cast.h:31
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define BOOLOID
Definition: pg_type.h:288
#define CharGetDatum(X)
Definition: postgres.h:399
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * targettype
Definition: parsenodes.h:3304
#define TYPTYPE_ENUM
Definition: pg_type.h:723
#define Anum_pg_cast_castcontext
Definition: pg_cast.h:81
#define elog
Definition: elog.h:219
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4740
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 862 of file functioncmds.c.

References ACL_CREATE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, Assert, castNode, ClanguageId, compute_function_attributes(), compute_return_type(), construct_array(), ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), CreateFunctionStmt::funcname, get_base_element_type(), get_namespace_name(), get_transform_oid(), GETSTRUCT, GetUserId(), HeapTupleGetOid, HeapTupleIsValid, i, INTERNALlanguageId, interpret_AS_clause(), interpret_function_parameter_list(), InvalidOid, CreateFunctionStmt::is_procedure, LANGNAME, lappend_oid(), lfirst_node, lfirst_oid, list_length(), NameStr, NIL, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_PROCEDURE, OBJECT_SCHEMA, ObjectIdGetDatum, OidIsValid, OIDOID, CreateFunctionStmt::options, palloc(), CreateFunctionStmt::parameters, pg_language_aclcheck(), pg_namespace_aclcheck(), PLTemplateExists(), PointerGetDatum, ProcedureCreate(), PROPARALLEL_UNSAFE, PROVOLATILE_VOLATILE, QualifiedNameGetCreationNamespace(), ReleaseSysCache(), CreateFunctionStmt::replace, CreateFunctionStmt::returnType, SearchSysCache1(), superuser(), typenameTypeId(), and VOIDOID.

Referenced by ProcessUtilitySlow().

863 {
864  char *probin_str;
865  char *prosrc_str;
866  Oid prorettype;
867  bool returnsSet;
868  char *language;
869  Oid languageOid;
870  Oid languageValidator;
871  Node *transformDefElem = NULL;
872  char *funcname;
873  Oid namespaceId;
874  AclResult aclresult;
875  oidvector *parameterTypes;
876  ArrayType *allParameterTypes;
877  ArrayType *parameterModes;
878  ArrayType *parameterNames;
879  List *parameterDefaults;
880  Oid variadicArgType;
881  List *trftypes_list = NIL;
882  ArrayType *trftypes;
883  Oid requiredResultType;
884  bool isWindowFunc,
885  isStrict,
886  security,
887  isLeakProof;
888  char volatility;
889  ArrayType *proconfig;
890  float4 procost;
891  float4 prorows;
892  HeapTuple languageTuple;
893  Form_pg_language languageStruct;
894  List *as_clause;
895  char parallel;
896 
897  /* Convert list of names to a name and namespace */
898  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
899  &funcname);
900 
901  /* Check we have creation rights in target namespace */
902  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
903  if (aclresult != ACLCHECK_OK)
904  aclcheck_error(aclresult, OBJECT_SCHEMA,
905  get_namespace_name(namespaceId));
906 
907  /* Set default attributes */
908  isWindowFunc = false;
909  isStrict = false;
910  security = false;
911  isLeakProof = false;
912  volatility = PROVOLATILE_VOLATILE;
913  proconfig = NULL;
914  procost = -1; /* indicates not set */
915  prorows = -1; /* indicates not set */
916  parallel = PROPARALLEL_UNSAFE;
917 
918  /* Extract non-default attributes from stmt->options list */
920  stmt->is_procedure,
921  stmt->options,
922  &as_clause, &language, &transformDefElem,
923  &isWindowFunc, &volatility,
924  &isStrict, &security, &isLeakProof,
925  &proconfig, &procost, &prorows, &parallel);
926 
927  /* Look up the language and validate permissions */
928  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
929  if (!HeapTupleIsValid(languageTuple))
930  ereport(ERROR,
931  (errcode(ERRCODE_UNDEFINED_OBJECT),
932  errmsg("language \"%s\" does not exist", language),
933  (PLTemplateExists(language) ?
934  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
935 
936  languageOid = HeapTupleGetOid(languageTuple);
937  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
938 
939  if (languageStruct->lanpltrusted)
940  {
941  /* if trusted language, need USAGE privilege */
942  AclResult aclresult;
943 
944  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
945  if (aclresult != ACLCHECK_OK)
946  aclcheck_error(aclresult, OBJECT_LANGUAGE,
947  NameStr(languageStruct->lanname));
948  }
949  else
950  {
951  /* if untrusted language, must be superuser */
952  if (!superuser())
954  NameStr(languageStruct->lanname));
955  }
956 
957  languageValidator = languageStruct->lanvalidator;
958 
959  ReleaseSysCache(languageTuple);
960 
961  /*
962  * Only superuser is allowed to create leakproof functions because
963  * leakproof functions can see tuples which have not yet been filtered out
964  * by security barrier views or row level security policies.
965  */
966  if (isLeakProof && !superuser())
967  ereport(ERROR,
968  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
969  errmsg("only superuser can define a leakproof function")));
970 
971  if (transformDefElem)
972  {
973  ListCell *lc;
974 
975  foreach(lc, castNode(List, transformDefElem))
976  {
977  Oid typeid = typenameTypeId(NULL,
978  lfirst_node(TypeName, lc));
979  Oid elt = get_base_element_type(typeid);
980 
981  typeid = elt ? elt : typeid;
982 
983  get_transform_oid(typeid, languageOid, false);
984  trftypes_list = lappend_oid(trftypes_list, typeid);
985  }
986  }
987 
988  /*
989  * Convert remaining parameters of CREATE to form wanted by
990  * ProcedureCreate.
991  */
993  stmt->parameters,
994  languageOid,
996  &parameterTypes,
997  &allParameterTypes,
998  &parameterModes,
999  &parameterNames,
1000  &parameterDefaults,
1001  &variadicArgType,
1002  &requiredResultType);
1003 
1004  if (stmt->is_procedure)
1005  {
1006  Assert(!stmt->returnType);
1007 
1008  prorettype = InvalidOid;
1009  returnsSet = false;
1010  }
1011  else if (stmt->returnType)
1012  {
1013  /* explicit RETURNS clause */
1014  compute_return_type(stmt->returnType, languageOid,
1015  &prorettype, &returnsSet);
1016  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1017  ereport(ERROR,
1018  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1019  errmsg("function result type must be %s because of OUT parameters",
1020  format_type_be(requiredResultType))));
1021  }
1022  else if (OidIsValid(requiredResultType))
1023  {
1024  /* default RETURNS clause from OUT parameters */
1025  prorettype = requiredResultType;
1026  returnsSet = false;
1027  }
1028  else
1029  {
1030  ereport(ERROR,
1031  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1032  errmsg("function result type must be specified")));
1033  /* Alternative possibility: default to RETURNS VOID */
1034  prorettype = VOIDOID;
1035  returnsSet = false;
1036  }
1037 
1038  if (list_length(trftypes_list) > 0)
1039  {
1040  ListCell *lc;
1041  Datum *arr;
1042  int i;
1043 
1044  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1045  i = 0;
1046  foreach(lc, trftypes_list)
1047  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1048  trftypes = construct_array(arr, list_length(trftypes_list),
1049  OIDOID, sizeof(Oid), true, 'i');
1050  }
1051  else
1052  {
1053  /* store SQL NULL instead of empty array */
1054  trftypes = NULL;
1055  }
1056 
1057  interpret_AS_clause(languageOid, language, funcname, as_clause,
1058  &prosrc_str, &probin_str);
1059 
1060  /*
1061  * Set default values for COST and ROWS depending on other parameters;
1062  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1063  * values, keep it in sync if you change them.
1064  */
1065  if (procost < 0)
1066  {
1067  /* SQL and PL-language functions are assumed more expensive */
1068  if (languageOid == INTERNALlanguageId ||
1069  languageOid == ClanguageId)
1070  procost = 1;
1071  else
1072  procost = 100;
1073  }
1074  if (prorows < 0)
1075  {
1076  if (returnsSet)
1077  prorows = 1000;
1078  else
1079  prorows = 0; /* dummy value if not returnsSet */
1080  }
1081  else if (!returnsSet)
1082  ereport(ERROR,
1083  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1084  errmsg("ROWS is not applicable when function does not return a set")));
1085 
1086  /*
1087  * And now that we have all the parameters, and know we're permitted to do
1088  * so, go ahead and create the function.
1089  */
1090  return ProcedureCreate(funcname,
1091  namespaceId,
1092  stmt->replace,
1093  returnsSet,
1094  prorettype,
1095  GetUserId(),
1096  languageOid,
1097  languageValidator,
1098  prosrc_str, /* converted to text later */
1099  probin_str, /* converted to text later */
1100  false, /* not an aggregate */
1101  isWindowFunc,
1102  security,
1103  isLeakProof,
1104  isStrict,
1105  volatility,
1106  parallel,
1107  parameterTypes,
1108  PointerGetDatum(allParameterTypes),
1109  PointerGetDatum(parameterModes),
1110  PointerGetDatum(parameterNames),
1111  parameterDefaults,
1112  PointerGetDatum(trftypes),
1113  PointerGetDatum(proconfig),
1114  procost,
1115  prorows);
1116 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:544
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define INTERNALlanguageId
Definition: pg_language.h:74
Oid GetUserId(void)
Definition: miscinit.c:284
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
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, char *parallel_p)
Definition: functioncmds.c:640
#define OIDOID
Definition: pg_type.h:328
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
#define PointerGetDatum(X)
Definition: postgres.h:539
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:86
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:513
#define ClanguageId
Definition: pg_language.h:77
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, char **prosrc_str_p, char **probin_str_p)
Definition: functioncmds.c:802
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:594
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4690
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4664
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define VOIDOID
Definition: pg_type.h:690
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define lfirst_node(type, lc)
Definition: pg_list.h:109
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5583
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5574
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
float float4
Definition: c.h:446
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:519
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, bool isAgg, bool isWindowFunc, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, float4 procost, float4 prorows)
Definition: pg_proc.c:67
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
TypeName * returnType
Definition: parsenodes.h:2758
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:182
static int list_length(const List *l)
Definition: pg_list.h:89
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2575
FormData_pg_language * Form_pg_language
Definition: pg_language.h:51
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:565
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1808 of file functioncmds.c.

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, Anum_pg_transform_trffromsql, Anum_pg_transform_trflang, Anum_pg_transform_trftosql, Anum_pg_transform_trftype, CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), CreateTransformStmt::fromsql, get_language_oid(), get_typtype(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, INTERNALOID, InvalidOid, InvokeObjectPostCreateHook, CreateTransformStmt::lang, LanguageRelationId, LookupFuncWithArgs(), MemSet, NameListToString(), Natts_pg_transform, OBJECT_FUNCTION, OBJECT_LANGUAGE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ObjectWithArgs::objname, OidIsValid, pg_language_aclcheck(), pg_proc_aclcheck(), pg_proc_ownercheck(), pg_type_aclcheck(), pg_type_ownercheck(), ProcedureRelationId, PROCOID, recordDependencyOn(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), CreateTransformStmt::replace, RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), HeapTupleData::t_self, CreateTransformStmt::tosql, TransformRelationId, TRFTYPELANG, CreateTransformStmt::type_name, TypeNameToString(), typenameTypeId(), TypeRelationId, TYPTYPE_DOMAIN, TYPTYPE_PSEUDO, and values.

Referenced by ProcessUtilitySlow().

1809 {
1810  Oid typeid;
1811  char typtype;
1812  Oid langid;
1813  Oid fromsqlfuncid;
1814  Oid tosqlfuncid;
1815  AclResult aclresult;
1816  Form_pg_proc procstruct;
1818  bool nulls[Natts_pg_transform];
1819  bool replaces[Natts_pg_transform];
1820  Oid transformid;
1821  HeapTuple tuple;
1822  HeapTuple newtuple;
1823  Relation relation;
1824  ObjectAddress myself,
1825  referenced;
1826  bool is_replace;
1827 
1828  /*
1829  * Get the type
1830  */
1831  typeid = typenameTypeId(NULL, stmt->type_name);
1832  typtype = get_typtype(typeid);
1833 
1834  if (typtype == TYPTYPE_PSEUDO)
1835  ereport(ERROR,
1836  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1837  errmsg("data type %s is a pseudo-type",
1838  TypeNameToString(stmt->type_name))));
1839 
1840  if (typtype == TYPTYPE_DOMAIN)
1841  ereport(ERROR,
1842  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1843  errmsg("data type %s is a domain",
1844  TypeNameToString(stmt->type_name))));
1845 
1846  if (!pg_type_ownercheck(typeid, GetUserId()))
1848 
1849  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1850  if (aclresult != ACLCHECK_OK)
1851  aclcheck_error_type(aclresult, typeid);
1852 
1853  /*
1854  * Get the language
1855  */
1856  langid = get_language_oid(stmt->lang, false);
1857 
1858  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1859  if (aclresult != ACLCHECK_OK)
1860  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1861 
1862  /*
1863  * Get the functions
1864  */
1865  if (stmt->fromsql)
1866  {
1867  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1868 
1869  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1871 
1872  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1873  if (aclresult != ACLCHECK_OK)
1875 
1876  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1877  if (!HeapTupleIsValid(tuple))
1878  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1879  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1880  if (procstruct->prorettype != INTERNALOID)
1881  ereport(ERROR,
1882  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1883  errmsg("return data type of FROM SQL function must be %s",
1884  "internal")));
1885  check_transform_function(procstruct);
1886  ReleaseSysCache(tuple);
1887  }
1888  else
1889  fromsqlfuncid = InvalidOid;
1890 
1891  if (stmt->tosql)
1892  {
1893  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1894 
1895  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1897 
1898  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1899  if (aclresult != ACLCHECK_OK)
1901 
1902  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1903  if (!HeapTupleIsValid(tuple))
1904  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1905  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1906  if (procstruct->prorettype != typeid)
1907  ereport(ERROR,
1908  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1909  errmsg("return data type of TO SQL function must be the transform data type")));
1910  check_transform_function(procstruct);
1911  ReleaseSysCache(tuple);
1912  }
1913  else
1914  tosqlfuncid = InvalidOid;
1915 
1916  /*
1917  * Ready to go
1918  */
1919  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1920  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1921  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1922  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1923 
1924  MemSet(nulls, false, sizeof(nulls));
1925 
1927 
1928  tuple = SearchSysCache2(TRFTYPELANG,
1929  ObjectIdGetDatum(typeid),
1930  ObjectIdGetDatum(langid));
1931  if (HeapTupleIsValid(tuple))
1932  {
1933  if (!stmt->replace)
1934  ereport(ERROR,
1936  errmsg("transform for type %s language \"%s\" already exists",
1937  format_type_be(typeid),
1938  stmt->lang)));
1939 
1940  MemSet(replaces, false, sizeof(replaces));
1941  replaces[Anum_pg_transform_trffromsql - 1] = true;
1942  replaces[Anum_pg_transform_trftosql - 1] = true;
1943 
1944  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1945  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1946 
1947  transformid = HeapTupleGetOid(tuple);
1948  ReleaseSysCache(tuple);
1949  is_replace = true;
1950  }
1951  else
1952  {
1953  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1954  transformid = CatalogTupleInsert(relation, newtuple);
1955  is_replace = false;
1956  }
1957 
1958  if (is_replace)
1959  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1960 
1961  /* make dependency entries */
1962  myself.classId = TransformRelationId;
1963  myself.objectId = transformid;
1964  myself.objectSubId = 0;
1965 
1966  /* dependency on language */
1967  referenced.classId = LanguageRelationId;
1968  referenced.objectId = langid;
1969  referenced.objectSubId = 0;
1970  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1971 
1972  /* dependency on type */
1973  referenced.classId = TypeRelationId;
1974  referenced.objectId = typeid;
1975  referenced.objectSubId = 0;
1976  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1977 
1978  /* dependencies on functions */
1979  if (OidIsValid(fromsqlfuncid))
1980  {
1981  referenced.classId = ProcedureRelationId;
1982  referenced.objectId = fromsqlfuncid;
1983  referenced.objectSubId = 0;
1984  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1985  }
1986  if (OidIsValid(tosqlfuncid))
1987  {
1988  referenced.classId = ProcedureRelationId;
1989  referenced.objectId = tosqlfuncid;
1990  referenced.objectSubId = 0;
1991  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1992  }
1993 
1994  /* dependency on extension */
1995  recordDependencyOnCurrentExtension(&myself, is_replace);
1996 
1997  /* Post creation hook for new transform */
1999 
2000  heap_freetuple(newtuple);
2001 
2002  heap_close(relation, RowExclusiveLock);
2003 
2004  return myself;
2005 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
ObjectWithArgs * tosql
Definition: parsenodes.h:3321
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define TransformRelationId
Definition: pg_transform.h:25
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define ProcedureRelationId
Definition: pg_proc.h:33
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:191
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:553
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2383
#define MemSet(start, val, len)
Definition: c.h:897
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4778
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:594
#define Anum_pg_transform_trftosql
Definition: pg_transform.h:45
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4664
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3663
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Natts_pg_transform
Definition: pg_transform.h:41
#define Anum_pg_transform_trflang
Definition: pg_transform.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2028
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3063
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3320
#define Anum_pg_transform_trffromsql
Definition: pg_transform.h:44
#define INTERNALOID
Definition: pg_type.h:698
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
#define Anum_pg_transform_trftype
Definition: pg_transform.h:42
TypeName * type_name
Definition: parsenodes.h:3318
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4652
#define LanguageRelationId
Definition: pg_language.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4740
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4830
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ DropCastById()

void DropCastById ( Oid  castOid)

Definition at line 1747 of file functioncmds.c.

References BTEqualStrategyNumber, CastOidIndexId, CastRelationId, CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1748 {
1749  Relation relation;
1750  ScanKeyData scankey;
1751  SysScanDesc scan;
1752  HeapTuple tuple;
1753 
1755 
1756  ScanKeyInit(&scankey,
1758  BTEqualStrategyNumber, F_OIDEQ,
1759  ObjectIdGetDatum(castOid));
1760  scan = systable_beginscan(relation, CastOidIndexId, true,
1761  NULL, 1, &scankey);
1762 
1763  tuple = systable_getnext(scan);
1764  if (!HeapTupleIsValid(tuple))
1765  elog(ERROR, "could not find tuple for cast %u", castOid);
1766  CatalogTupleDelete(relation, &tuple->t_self);
1767 
1768  systable_endscan(scan);
1769  heap_close(relation, RowExclusiveLock);
1770 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CastOidIndexId
Definition: indexing.h:107
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define CastRelationId
Definition: pg_cast.h:31
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DropTransformById()

void DropTransformById ( Oid  transformOid)

Definition at line 2033 of file functioncmds.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, TransformOidIndexId, and TransformRelationId.

Referenced by doDeletion().

2034 {
2035  Relation relation;
2036  ScanKeyData scankey;
2037  SysScanDesc scan;
2038  HeapTuple tuple;
2039 
2041 
2042  ScanKeyInit(&scankey,
2044  BTEqualStrategyNumber, F_OIDEQ,
2045  ObjectIdGetDatum(transformOid));
2046  scan = systable_beginscan(relation, TransformOidIndexId, true,
2047  NULL, 1, &scankey);
2048 
2049  tuple = systable_getnext(scan);
2050  if (!HeapTupleIsValid(tuple))
2051  elog(ERROR, "could not find tuple for transform %u", transformOid);
2052  CatalogTupleDelete(relation, &tuple->t_self);
2053 
2054  systable_endscan(scan);
2055  heap_close(relation, RowExclusiveLock);
2056 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define TransformRelationId
Definition: pg_transform.h:25
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define TransformOidIndexId
Definition: indexing.h:242
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ ExecuteCallStmt()

void ExecuteCallStmt ( ParseState pstate,
CallStmt stmt,
bool  atomic 
)

Definition at line 2215 of file functioncmds.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, Anum_pg_proc_proconfig, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, FuncCall::args, FuncExpr::args, CallContext::atomic, castNode, CreateExecutorState(), CreateExprContext(), elog, ereport, errcode(), errmsg_plural(), ERROR, ExecEvalExprSwitchContext(), ExecPrepareExpr(), EXPR_KIND_CALL_ARGUMENT, fmgr_info(), FreeExecutorState(), FUNC_MAX_ARGS, CallStmt::funccall, FuncExpr::funcid, FuncCall::funcname, FunctionCallInvoke, get_func_name(), GetUserId(), heap_attisnull(), HeapTupleIsValid, i, InitFunctionCallInfoData, FuncExpr::inputcollid, InvokeFunctionExecuteHook, lappend(), lfirst, list_length(), FuncCall::location, makeNode, NIL, OBJECT_PROCEDURE, ObjectIdGetDatum, ParseState::p_last_srf, ParseFuncOrColumn(), pg_proc_aclcheck(), PROCOID, ReleaseSysCache(), SearchSysCache1(), transformExpr(), and val.

Referenced by standard_ProcessUtility().

2216 {
2217  List *targs;
2218  ListCell *lc;
2219  Node *node;
2220  FuncExpr *fexpr;
2221  int nargs;
2222  int i;
2223  AclResult aclresult;
2224  FmgrInfo flinfo;
2225  FunctionCallInfoData fcinfo;
2226  CallContext *callcontext;
2227  EState *estate;
2228  ExprContext *econtext;
2229  HeapTuple tp;
2230 
2231  /* We need to do parse analysis on the procedure call and its arguments */
2232  targs = NIL;
2233  foreach(lc, stmt->funccall->args)
2234  {
2235  targs = lappend(targs, transformExpr(pstate,
2236  (Node *) lfirst(lc),
2238  }
2239 
2240  node = ParseFuncOrColumn(pstate,
2241  stmt->funccall->funcname,
2242  targs,
2243  pstate->p_last_srf,
2244  stmt->funccall,
2245  true,
2246  stmt->funccall->location);
2247 
2248  fexpr = castNode(FuncExpr, node);
2249 
2250  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2251  if (aclresult != ACLCHECK_OK)
2252  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2253 
2254  nargs = list_length(fexpr->args);
2255 
2256  /* safety check; see ExecInitFunc() */
2257  if (nargs > FUNC_MAX_ARGS)
2258  ereport(ERROR,
2259  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2260  errmsg_plural("cannot pass more than %d argument to a procedure",
2261  "cannot pass more than %d arguments to a procedure",
2262  FUNC_MAX_ARGS,
2263  FUNC_MAX_ARGS)));
2264 
2265  /* Prep the context object we'll pass to the procedure */
2266  callcontext = makeNode(CallContext);
2267  callcontext->atomic = atomic;
2268 
2269  /*
2270  * If proconfig is set we can't allow transaction commands because of the
2271  * way the GUC stacking works: The transaction boundary would have to pop
2272  * the proconfig setting off the stack. That restriction could be lifted
2273  * by redesigning the GUC nesting mechanism a bit.
2274  */
2276  if (!HeapTupleIsValid(tp))
2277  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2279  callcontext->atomic = true;
2280  ReleaseSysCache(tp);
2281 
2282  /* Initialize function call structure */
2284  fmgr_info(fexpr->funcid, &flinfo);
2285  InitFunctionCallInfoData(fcinfo, &flinfo, nargs, fexpr->inputcollid, (Node *) callcontext, NULL);
2286 
2287  /*
2288  * Evaluate procedure arguments inside a suitable execution context. Note
2289  * we can't free this context till the procedure returns.
2290  */
2291  estate = CreateExecutorState();
2292  econtext = CreateExprContext(estate);
2293 
2294  i = 0;
2295  foreach(lc, fexpr->args)
2296  {
2297  ExprState *exprstate;
2298  Datum val;
2299  bool isnull;
2300 
2301  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2302 
2303  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2304 
2305  fcinfo.arg[i] = val;
2306  fcinfo.argnull[i] = isnull;
2307 
2308  i++;
2309  }
2310 
2311  FunctionCallInvoke(&fcinfo);
2312 
2313  FreeExecutorState(estate);
2314 }
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:56
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:297
List * args
Definition: primnodes.h:457
Oid GetUserId(void)
Definition: miscinit.c:284
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
FuncCall * funccall
Definition: parsenodes.h:2817
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
int location
Definition: parsenodes.h:358
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:487
#define Anum_pg_proc_proconfig
Definition: pg_proc.h:117
#define FUNC_MAX_ARGS
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
Oid funcid
Definition: primnodes.h:449
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:73
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1397
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
EState * CreateExecutorState(void)
Definition: execUtils.c:80
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
List * lappend(List *list, void *datum)
Definition: list.c:128
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
AclResult
Definition: acl.h:178
Node * p_last_srf
Definition: parse_node.h:206
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define makeNode(_type_)
Definition: nodes.h:561
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
Oid inputcollid
Definition: primnodes.h:456
#define lfirst(lc)
Definition: pg_list.h:106
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
List * args
Definition: parsenodes.h:350
static int list_length(const List *l)
Definition: pg_list.h:89
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4652
int i
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:225
#define elog
Definition: elog.h:219
List * funcname
Definition: parsenodes.h:349
Definition: pg_list.h:45
long val
Definition: informix.c:689

◆ ExecuteDoStmt()

void ExecuteDoStmt ( DoStmt stmt,
bool  atomic 
)

Definition at line 2089 of file functioncmds.c.

References ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, arg, DefElem::arg, DoStmt::args, InlineCodeBlock::atomic, DefElem::defname, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, GetUserId(), HeapTupleGetOid, HeapTupleIsValid, InlineCodeBlock::langIsTrusted, LANGNAME, InlineCodeBlock::langOid, lfirst, makeNode, NameStr, OBJECT_LANGUAGE, OidFunctionCall1, OidIsValid, pg_language_aclcheck(), PLTemplateExists(), PointerGetDatum, ReleaseSysCache(), SearchSysCache1(), InlineCodeBlock::source_text, strVal, and superuser().

Referenced by standard_ProcessUtility().

2090 {
2092  ListCell *arg;
2093  DefElem *as_item = NULL;
2094  DefElem *language_item = NULL;
2095  char *language;
2096  Oid laninline;
2097  HeapTuple languageTuple;
2098  Form_pg_language languageStruct;
2099 
2100  /* Process options we got from gram.y */
2101  foreach(arg, stmt->args)
2102  {
2103  DefElem *defel = (DefElem *) lfirst(arg);
2104 
2105  if (strcmp(defel->defname, "as") == 0)
2106  {
2107  if (as_item)
2108  ereport(ERROR,
2109  (errcode(ERRCODE_SYNTAX_ERROR),
2110  errmsg("conflicting or redundant options")));
2111  as_item = defel;
2112  }
2113  else if (strcmp(defel->defname, "language") == 0)
2114  {
2115  if (language_item)
2116  ereport(ERROR,
2117  (errcode(ERRCODE_SYNTAX_ERROR),
2118  errmsg("conflicting or redundant options")));
2119  language_item = defel;
2120  }
2121  else
2122  elog(ERROR, "option \"%s\" not recognized",
2123  defel->defname);
2124  }
2125 
2126  if (as_item)
2127  codeblock->source_text = strVal(as_item->arg);
2128  else
2129  ereport(ERROR,
2130  (errcode(ERRCODE_SYNTAX_ERROR),
2131  errmsg("no inline code specified")));
2132 
2133  /* if LANGUAGE option wasn't specified, use the default */
2134  if (language_item)
2135  language = strVal(language_item->arg);
2136  else
2137  language = "plpgsql";
2138 
2139  /* Look up the language and validate permissions */
2140  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2141  if (!HeapTupleIsValid(languageTuple))
2142  ereport(ERROR,
2143  (errcode(ERRCODE_UNDEFINED_OBJECT),
2144  errmsg("language \"%s\" does not exist", language),
2145  (PLTemplateExists(language) ?
2146  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
2147 
2148  codeblock->langOid = HeapTupleGetOid(languageTuple);
2149  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2150  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2151  codeblock->atomic = atomic;
2152 
2153  if (languageStruct->lanpltrusted)
2154  {
2155  /* if trusted language, need USAGE privilege */
2156  AclResult aclresult;
2157 
2158  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2159  ACL_USAGE);
2160  if (aclresult != ACLCHECK_OK)
2161  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2162  NameStr(languageStruct->lanname));
2163  }
2164  else
2165  {
2166  /* if untrusted language, must be superuser */
2167  if (!superuser())
2169  NameStr(languageStruct->lanname));
2170  }
2171 
2172  /* get the handler function's OID */
2173  laninline = languageStruct->laninline;
2174  if (!OidIsValid(laninline))
2175  ereport(ERROR,
2176  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2177  errmsg("language \"%s\" does not support inline code execution",
2178  NameStr(languageStruct->lanname))));
2179 
2180  ReleaseSysCache(languageTuple);
2181 
2182  /* execute the inline handler */
2183  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2184 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:539
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4664
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:623
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:728
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
AclResult
Definition: acl.h:178
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:519
#define makeNode(_type_)
Definition: nodes.h:561
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: parsenodes.h:2798
FormData_pg_language * Form_pg_language
Definition: pg_language.h:51
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:565
void * arg
char * source_text
Definition: parsenodes.h:2804
char * defname
Definition: parsenodes.h:727
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ get_cast_oid()

Oid get_cast_oid ( Oid  sourcetypeid,
Oid  targettypeid,
bool  missing_ok 
)

Definition at line 1730 of file functioncmds.c.

References CASTSOURCETARGET, ereport, errcode(), errmsg(), ERROR, format_type_be(), GetSysCacheOid2, ObjectIdGetDatum, and OidIsValid.

Referenced by get_object_address().

1731 {
1732  Oid oid;
1733 
1735  ObjectIdGetDatum(sourcetypeid),
1736  ObjectIdGetDatum(targettypeid));
1737  if (!OidIsValid(oid) && !missing_ok)
1738  ereport(ERROR,
1739  (errcode(ERRCODE_UNDEFINED_OBJECT),
1740  errmsg("cast from type %s to type %s does not exist",
1741  format_type_be(sourcetypeid),
1742  format_type_be(targettypeid))));
1743  return oid;
1744 }
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ get_transform_oid()

Oid get_transform_oid ( Oid  type_id,
Oid  lang_id,
bool  missing_ok 
)

Definition at line 2015 of file functioncmds.c.

References ereport, errcode(), errmsg(), ERROR, format_type_be(), get_language_name(), GetSysCacheOid2, ObjectIdGetDatum, OidIsValid, and TRFTYPELANG.

Referenced by CreateFunction(), get_object_address(), and ProcedureCreate().

2016 {
2017  Oid oid;
2018 
2020  ObjectIdGetDatum(type_id),
2021  ObjectIdGetDatum(lang_id));
2022  if (!OidIsValid(oid) && !missing_ok)
2023  ereport(ERROR,
2024  (errcode(ERRCODE_UNDEFINED_OBJECT),
2025  errmsg("transform for type %s language \"%s\" does not exist",
2026  format_type_be(type_id),
2027  get_language_name(lang_id, false))));
2028  return oid;
2029 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1003
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ interpret_AS_clause()

static void interpret_AS_clause ( Oid  languageOid,
const char *  languageName,
char *  funcname,
List as,
char **  prosrc_str_p,
char **  probin_str_p 
)
static

Definition at line 802 of file functioncmds.c.

References Assert, ClanguageId, ereport, errcode(), errmsg(), ERROR, INTERNALlanguageId, linitial, list_length(), lsecond, NIL, and strVal.

Referenced by CreateFunction().

805 {
806  Assert(as != NIL);
807 
808  if (languageOid == ClanguageId)
809  {
810  /*
811  * For "C" language, store the file name in probin and, when given,
812  * the link symbol name in prosrc. If link symbol is omitted,
813  * substitute procedure name. We also allow link symbol to be
814  * specified as "-", since that was the habit in PG versions before
815  * 8.4, and there might be dump files out there that don't translate
816  * that back to "omitted".
817  */
818  *probin_str_p = strVal(linitial(as));
819  if (list_length(as) == 1)
820  *prosrc_str_p = funcname;
821  else
822  {
823  *prosrc_str_p = strVal(lsecond(as));
824  if (strcmp(*prosrc_str_p, "-") == 0)
825  *prosrc_str_p = funcname;
826  }
827  }
828  else
829  {
830  /* Everything else wants the given string in prosrc. */
831  *prosrc_str_p = strVal(linitial(as));
832  *probin_str_p = NULL;
833 
834  if (list_length(as) != 1)
835  ereport(ERROR,
836  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
837  errmsg("only one AS item needed for language \"%s\"",
838  languageName)));
839 
840  if (languageOid == INTERNALlanguageId)
841  {
842  /*
843  * In PostgreSQL versions before 6.5, the SQL name of the created
844  * function could not be different from the internal name, and
845  * "prosrc" wasn't used. So there is code out there that does
846  * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
847  * modicum of backwards compatibility, accept an empty "prosrc"
848  * value as meaning the supplied SQL function name.
849  */
850  if (strlen(*prosrc_str_p) == 0)
851  *prosrc_str_p = funcname;
852  }
853  }
854 }
#define NIL
Definition: pg_list.h:69
#define INTERNALlanguageId
Definition: pg_language.h:74
#define strVal(v)
Definition: value.h:54
#define ClanguageId
Definition: pg_language.h:77
int errcode(int sqlerrcode)
Definition: elog.c:575
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:688
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 585 of file functioncmds.c.

References DefElem::arg, ereport, errcode(), errmsg(), ERROR, PROPARALLEL_RESTRICTED, PROPARALLEL_SAFE, PROPARALLEL_UNSAFE, generate_unaccent_rules::str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

586 {
587  char *str = strVal(defel->arg);
588 
589  if (strcmp(str, "safe") == 0)
590  return PROPARALLEL_SAFE;
591  else if (strcmp(str, "unsafe") == 0)
592  return PROPARALLEL_UNSAFE;
593  else if (strcmp(str, "restricted") == 0)
594  return PROPARALLEL_RESTRICTED;
595  else
596  {
597  ereport(ERROR,
598  (errcode(ERRCODE_SYNTAX_ERROR),
599  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
600  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
601  }
602 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PROPARALLEL_RESTRICTED
Definition: pg_proc.h:5582
#define ERROR
Definition: elog.h:43
#define PROPARALLEL_SAFE
Definition: pg_proc.h:5581
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5583
Node * arg
Definition: parsenodes.h:728
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 567 of file functioncmds.c.

References DefElem::arg, elog, ERROR, PROVOLATILE_IMMUTABLE, PROVOLATILE_STABLE, PROVOLATILE_VOLATILE, generate_unaccent_rules::str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

568 {
569  char *str = strVal(defel->arg);
570 
571  if (strcmp(str, "immutable") == 0)
572  return PROVOLATILE_IMMUTABLE;
573  else if (strcmp(str, "stable") == 0)
574  return PROVOLATILE_STABLE;
575  else if (strcmp(str, "volatile") == 0)
576  return PROVOLATILE_VOLATILE;
577  else
578  {
579  elog(ERROR, "invalid volatility \"%s\"", str);
580  return 0; /* keep compiler quiet */
581  }
582 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5572
#define strVal(v)
Definition: value.h:54
#define ERROR
Definition: elog.h:43
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5573
Node * arg
Definition: parsenodes.h:728
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5574
#define elog
Definition: elog.h:219

◆ interpret_function_parameter_list()

void interpret_function_parameter_list ( ParseState pstate,
List parameters,
Oid  languageOid,
ObjectType  objtype,
oidvector **  parameterTypes,
ArrayType **  allParameterTypes,
ArrayType **  parameterModes,
ArrayType **  parameterNames,
List **  parameterDefaults,
Oid variadicArgType,
Oid requiredResultType 
)

Definition at line 182 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, ANYARRAYOID, ANYOID, FunctionParameter::argType, assign_expr_collations(), buildoidvector(), CharGetDatum, CHAROID, coerce_to_specific_type(), construct_array(), contain_var_clause(), CStringGetTextDatum, FunctionParameter::defexpr, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FUNCTION_DEFAULT, FUNC_PARAM_IN, FUNC_PARAM_INOUT, FUNC_PARAM_OUT, FUNC_PARAM_TABLE, FUNC_PARAM_VARIADIC, get_element_type(), GETSTRUCT, GetUserId(), i, InvalidOid, lappend(), lfirst, list_length(), LookupTypeName(), FunctionParameter::mode, FunctionParameter::name, NIL, NOTICE, OBJECT_AGGREGATE, OBJECT_PROCEDURE, ObjectIdGetDatum, OidIsValid, OIDOID, ParseState::p_rtable, palloc(), palloc0(), pg_type_aclcheck(), PointerGetDatum, px(), RECORDOID, ReleaseSysCache(), TypeName::setof, SQLlanguageId, TEXTOID, transformExpr(), TypeNameToString(), and typeTypeId().

Referenced by CreateFunction(), and DefineAggregate().

193 {
194  int parameterCount = list_length(parameters);
195  Oid *inTypes;
196  int inCount = 0;
197  Datum *allTypes;
198  Datum *paramModes;
199  Datum *paramNames;
200  int outCount = 0;
201  int varCount = 0;
202  bool have_names = false;
203  bool have_defaults = false;
204  ListCell *x;
205  int i;
206 
207  *variadicArgType = InvalidOid; /* default result */
208  *requiredResultType = InvalidOid; /* default result */
209 
210  inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
211  allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
212  paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
213  paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
214  *parameterDefaults = NIL;
215 
216  /* Scan the list and extract data into work arrays */
217  i = 0;
218  foreach(x, parameters)
219  {
221  TypeName *t = fp->argType;
222  bool isinput = false;
223  Oid toid;
224  Type typtup;
225  AclResult aclresult;
226 
227  typtup = LookupTypeName(NULL, t, NULL, false);
228  if (typtup)
229  {
230  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
231  {
232  /* As above, hard error if language is SQL */
233  if (languageOid == SQLlanguageId)
234  ereport(ERROR,
235  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
236  errmsg("SQL function cannot accept shell type %s",
237  TypeNameToString(t))));
238  /* We don't allow creating aggregates on shell types either */
239  else if (objtype == OBJECT_AGGREGATE)
240  ereport(ERROR,
241  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
242  errmsg("aggregate cannot accept shell type %s",
243  TypeNameToString(t))));
244  else
245  ereport(NOTICE,
246  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
247  errmsg("argument type %s is only a shell",
248  TypeNameToString(t))));
249  }
250  toid = typeTypeId(typtup);
251  ReleaseSysCache(typtup);
252  }
253  else
254  {
255  ereport(ERROR,
256  (errcode(ERRCODE_UNDEFINED_OBJECT),
257  errmsg("type %s does not exist",
258  TypeNameToString(t))));
259  toid = InvalidOid; /* keep compiler quiet */
260  }
261 
262  aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);
263  if (aclresult != ACLCHECK_OK)
264  aclcheck_error_type(aclresult, toid);
265 
266  if (t->setof)
267  {
268  if (objtype == OBJECT_AGGREGATE)
269  ereport(ERROR,
270  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
271  errmsg("aggregates cannot accept set arguments")));
272  else if (objtype == OBJECT_PROCEDURE)
273  ereport(ERROR,
274  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
275  errmsg("procedures cannot accept set arguments")));
276  else
277  ereport(ERROR,
278  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
279  errmsg("functions cannot accept set arguments")));
280  }
281 
282  if (objtype == OBJECT_PROCEDURE)
283  {
284  if (fp->mode == FUNC_PARAM_OUT || fp->mode == FUNC_PARAM_INOUT)
285  ereport(ERROR,
286  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
287  (errmsg("procedures cannot have OUT parameters"))));
288  }
289 
290  /* handle input parameters */
291  if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
292  {
293  /* other input parameters can't follow a VARIADIC parameter */
294  if (varCount > 0)
295  ereport(ERROR,
296  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
297  errmsg("VARIADIC parameter must be the last input parameter")));
298  inTypes[inCount++] = toid;
299  isinput = true;
300  }
301 
302  /* handle output parameters */
303  if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
304  {
305  if (outCount == 0) /* save first output param's type */
306  *requiredResultType = toid;
307  outCount++;
308  }
309 
310  if (fp->mode == FUNC_PARAM_VARIADIC)
311  {
312  *variadicArgType = toid;
313  varCount++;
314  /* validate variadic parameter type */
315  switch (toid)
316  {
317  case ANYARRAYOID:
318  case ANYOID:
319  /* okay */
320  break;
321  default:
322  if (!OidIsValid(get_element_type(toid)))
323  ereport(ERROR,
324  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
325  errmsg("VARIADIC parameter must be an array")));
326  break;
327  }
328  }
329 
330  allTypes[i] = ObjectIdGetDatum(toid);
331 
332  paramModes[i] = CharGetDatum(fp->mode);
333 
334  if (fp->name && fp->name[0])
335  {
336  ListCell *px;
337 
338  /*
339  * As of Postgres 9.0 we disallow using the same name for two
340  * input or two output function parameters. Depending on the
341  * function's language, conflicting input and output names might
342  * be bad too, but we leave it to the PL to complain if so.
343  */
344  foreach(px, parameters)
345  {
346  FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
347 
348  if (prevfp == fp)
349  break;
350  /* pure in doesn't conflict with pure out */
351  if ((fp->mode == FUNC_PARAM_IN ||
352  fp->mode == FUNC_PARAM_VARIADIC) &&
353  (prevfp->mode == FUNC_PARAM_OUT ||
354  prevfp->mode == FUNC_PARAM_TABLE))
355  continue;
356  if ((prevfp->mode == FUNC_PARAM_IN ||
357  prevfp->mode == FUNC_PARAM_VARIADIC) &&
358  (fp->mode == FUNC_PARAM_OUT ||
359  fp->mode == FUNC_PARAM_TABLE))
360  continue;
361  if (prevfp->name && prevfp->name[0] &&
362  strcmp(prevfp->name, fp->name) == 0)
363  ereport(ERROR,
364  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
365  errmsg("parameter name \"%s\" used more than once",
366  fp->name)));
367  }
368 
369  paramNames[i] = CStringGetTextDatum(fp->name);
370  have_names = true;
371  }
372 
373  if (fp->defexpr)
374  {
375  Node *def;
376 
377  if (!isinput)
378  ereport(ERROR,
379  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
380  errmsg("only input parameters can have default values")));
381 
382  def = transformExpr(pstate, fp->defexpr,
384  def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
385  assign_expr_collations(pstate, def);
386 
387  /*
388  * Make sure no variables are referred to (this is probably dead
389  * code now that add_missing_from is history).
390  */
391  if (list_length(pstate->p_rtable) != 0 ||
392  contain_var_clause(def))
393  ereport(ERROR,
394  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
395  errmsg("cannot use table references in parameter default value")));
396 
397  /*
398  * transformExpr() should have already rejected subqueries,
399  * aggregates, and window functions, based on the EXPR_KIND_ for a
400  * default expression.
401  *
402  * It can't return a set either --- but coerce_to_specific_type
403  * already checked that for us.
404  *
405  * Note: the point of these restrictions is to ensure that an
406  * expression that, on its face, hasn't got subplans, aggregates,
407  * etc cannot suddenly have them after function default arguments
408  * are inserted.
409  */
410 
411  *parameterDefaults = lappend(*parameterDefaults, def);
412  have_defaults = true;
413  }
414  else
415  {
416  if (isinput && have_defaults)
417  ereport(ERROR,
418  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
419  errmsg("input parameters after one with a default value must also have defaults")));
420  }
421 
422  i++;
423  }
424 
425  /* Now construct the proper outputs as needed */
426  *parameterTypes = buildoidvector(inTypes, inCount);
427 
428  if (outCount > 0 || varCount > 0)
429  {
430  *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
431  sizeof(Oid), true, 'i');
432  *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
433  1, true, 'c');
434  if (outCount > 1)
435  *requiredResultType = RECORDOID;
436  /* otherwise we set requiredResultType correctly above */
437  }
438  else
439  {
440  *allParameterTypes = NULL;
441  *parameterModes = NULL;
442  }
443 
444  if (have_names)
445  {
446  for (i = 0; i < parameterCount; i++)
447  {
448  if (paramNames[i] == PointerGetDatum(NULL))
449  paramNames[i] = CStringGetTextDatum("");
450  }
451  *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
452  -1, false, 'i');
453  }
454  else
455  *parameterNames = NULL;
456 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid GetUserId(void)
Definition: miscinit.c:284
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
#define PointerGetDatum(X)
Definition: postgres.h:539
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
bool contain_var_clause(Node *node)
Definition: var.c:331
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3663
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define SQLlanguageId
Definition: pg_language.h:80
bool setof
Definition: parsenodes.h:210
#define ANYOID
Definition: pg_type.h:686
#define ACL_USAGE
Definition: parsenodes.h:80
#define RECORDOID
Definition: pg_type.h:680
TypeName * argType
Definition: parsenodes.h:2776
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
#define ANYARRAYOID
Definition: pg_type.h:688
void * palloc0(Size size)
Definition: mcxt.c:864
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define CHAROID
Definition: pg_type.h:296
#define InvalidOid
Definition: postgres_ext.h:36
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
#define NOTICE
Definition: elog.h:37
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
#define CharGetDatum(X)
Definition: postgres.h:399
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
#define CStringGetTextDatum(s)
Definition: builtins.h:91
FunctionParameterMode mode
Definition: parsenodes.h:2777
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4740
Oid typeTypeId(Type tp)
Definition: parse_type.c:571
List * p_rtable
Definition: parse_node.h:174

◆ IsThereFunctionInNamespace()

void IsThereFunctionInNamespace ( const char *  proname,
int  pronargs,
oidvector proargtypes,
Oid  nspOid 
)

Definition at line 2066 of file functioncmds.c.

References CStringGetDatum, ereport, errcode(), errmsg(), ERROR, funcname_signature_string(), get_namespace_name(), NIL, ObjectIdGetDatum, PointerGetDatum, PROCNAMEARGSNSP, SearchSysCacheExists3, and oidvector::values.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

2068 {
2069  /* check for duplicate name (more friendly than unique-index failure) */
2071  CStringGetDatum(proname),
2072  PointerGetDatum(proargtypes),
2073  ObjectIdGetDatum(nspOid)))
2074  ereport(ERROR,
2075  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2076  errmsg("function %s already exists in schema \"%s\"",
2077  funcname_signature_string(proname, pronargs,
2078  NIL, proargtypes->values),
2079  get_namespace_name(nspOid))));
2080 }
#define NIL
Definition: pg_list.h:69
#define PointerGetDatum(X)
Definition: postgres.h:539
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:186
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:552
#define CStringGetDatum(X)
Definition: postgres.h:561
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1903
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

Definition at line 1125 of file functioncmds.c.

References AGGFNOID, AggregateRelationId, CatalogTupleDelete(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ProcedureRelationId, PROCOID, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

1126 {
1127  Relation relation;
1128  HeapTuple tup;
1129  bool isagg;
1130 
1131  /*
1132  * Delete the pg_proc tuple.
1133  */
1135 
1136  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1137  if (!HeapTupleIsValid(tup)) /* should not happen */
1138  elog(ERROR, "cache lookup failed for function %u", funcOid);
1139 
1140  isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
1141 
1142  CatalogTupleDelete(relation, &tup->t_self);
1143 
1144  ReleaseSysCache(tup);
1145 
1146  heap_close(relation, RowExclusiveLock);
1147 
1148  /*
1149  * If there's a pg_aggregate tuple, delete that too.
1150  */
1151  if (isagg)
1152  {
1154 
1155  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1156  if (!HeapTupleIsValid(tup)) /* should not happen */
1157  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1158 
1159  CatalogTupleDelete(relation, &tup->t_self);
1160 
1161  ReleaseSysCache(tup);
1162 
1163  heap_close(relation, RowExclusiveLock);
1164  }
1165 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ProcedureRelationId
Definition: pg_proc.h:33
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define AggregateRelationId
Definition: pg_aggregate.h:53
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219

◆ SetFunctionArgType()

void SetFunctionArgType ( Oid  funcOid,
int  argIndex,
Oid  newArgType 
)

Definition at line 1367 of file functioncmds.c.

References CatalogTupleUpdate(), DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectAddressSet, ObjectIdGetDatum, OPAQUEOID, ProcedureRelationId, PROCOID, recordDependencyOn(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, and TypeRelationId.

Referenced by findTypeInputFunction(), and findTypeOutputFunction().

1368 {
1369  Relation pg_proc_rel;
1370  HeapTuple tup;
1371  Form_pg_proc procForm;
1372  ObjectAddress func_address;
1373  ObjectAddress type_address;
1374 
1376 
1377  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1378  if (!HeapTupleIsValid(tup)) /* should not happen */
1379  elog(ERROR, "cache lookup failed for function %u", funcOid);
1380  procForm = (Form_pg_proc) GETSTRUCT(tup);
1381 
1382  if (argIndex < 0 || argIndex >= procForm->pronargs ||
1383  procForm->proargtypes.values[argIndex] != OPAQUEOID)
1384  elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1385 
1386  /* okay to overwrite copied tuple */
1387  procForm->proargtypes.values[argIndex] = newArgType;
1388 
1389  /* update the catalog and its indexes */
1390  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1391 
1392  heap_close(pg_proc_rel, RowExclusiveLock);
1393 
1394  /*
1395  * Also update the dependency to the new type. Opaque is a pinned type, so
1396  * there is no old dependency record for it that we would need to remove.
1397  */
1398  ObjectAddressSet(type_address, TypeRelationId, newArgType);
1399  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1400  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1401 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ProcedureRelationId
Definition: pg_proc.h:33
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
#define TypeRelationId
Definition: pg_type.h:34
#define OPAQUEOID
Definition: pg_type.h:700
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define elog
Definition: elog.h:219

◆ SetFunctionReturnType()

void SetFunctionReturnType ( Oid  funcOid,
Oid  newRetType 
)

Definition at line 1325 of file functioncmds.c.

References CatalogTupleUpdate(), DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectAddressSet, ObjectIdGetDatum, OPAQUEOID, ProcedureRelationId, PROCOID, recordDependencyOn(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, and TypeRelationId.

Referenced by CreateProceduralLanguage(), CreateTrigger(), and DefineType().

1326 {
1327  Relation pg_proc_rel;
1328  HeapTuple tup;
1329  Form_pg_proc procForm;
1330  ObjectAddress func_address;
1331  ObjectAddress type_address;
1332 
1334 
1335  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1336  if (!HeapTupleIsValid(tup)) /* should not happen */
1337  elog(ERROR, "cache lookup failed for function %u", funcOid);
1338  procForm = (Form_pg_proc) GETSTRUCT(tup);
1339 
1340  if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1341  elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1342 
1343  /* okay to overwrite copied tuple */
1344  procForm->prorettype = newRetType;
1345 
1346  /* update the catalog and its indexes */
1347  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1348 
1349  heap_close(pg_proc_rel, RowExclusiveLock);
1350 
1351  /*
1352  * Also update the dependency to the new type. Opaque is a pinned type, so
1353  * there is no old dependency record for it that we would need to remove.
1354  */
1355  ObjectAddressSet(type_address, TypeRelationId, newRetType);
1356  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1357  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1358 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ProcedureRelationId
Definition: pg_proc.h:33
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
#define TypeRelationId
Definition: pg_type.h:34
#define OPAQUEOID
Definition: pg_type.h:700
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define elog
Definition: elog.h:219

◆ update_proconfig_value()

static ArrayType* update_proconfig_value ( ArrayType a,
List set_items 
)
static

Definition at line 610 of file functioncmds.c.

References ExtractSetVariableArgs(), GUCArrayAdd(), GUCArrayDelete(), VariableSetStmt::kind, lfirst_node, VariableSetStmt::name, and VAR_RESET_ALL.

Referenced by AlterFunction(), and compute_function_attributes().

611 {
612  ListCell *l;
613 
614  foreach(l, set_items)
615  {
617 
618  if (sstmt->kind == VAR_RESET_ALL)
619  a = NULL;
620  else
621  {
622  char *valuestr = ExtractSetVariableArgs(sstmt);
623 
624  if (valuestr)
625  a = GUCArrayAdd(a, sstmt->name, valuestr);
626  else /* RESET */
627  a = GUCArrayDelete(a, sstmt->name);
628  }
629  }
630 
631  return a;
632 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:9513
VariableSetKind kind
Definition: parsenodes.h:1981
#define lfirst_node(type, lc)
Definition: pg_list.h:109
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:9593
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:7456