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/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_attributes_sql_style (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 compute_attributes_with_style (ParseState *pstate, bool is_procedure, List *parameters, bool *isStrict_p, char *volatility_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)
 
void ExecuteCallStmt (ParseState *pstate, CallStmt *stmt)
 

Function Documentation

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1227 of file functioncmds.c.

References ACL_KIND_PROC, 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().

1228 {
1229  HeapTuple tup;
1230  Oid funcOid;
1231  Form_pg_proc procForm;
1232  bool is_procedure;
1233  Relation rel;
1234  ListCell *l;
1235  DefElem *volatility_item = NULL;
1236  DefElem *strict_item = NULL;
1237  DefElem *security_def_item = NULL;
1238  DefElem *leakproof_item = NULL;
1239  List *set_items = NIL;
1240  DefElem *cost_item = NULL;
1241  DefElem *rows_item = NULL;
1242  DefElem *parallel_item = NULL;
1243  ObjectAddress address;
1244 
1246 
1247  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1248 
1249  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1250  if (!HeapTupleIsValid(tup)) /* should not happen */
1251  elog(ERROR, "cache lookup failed for function %u", funcOid);
1252 
1253  procForm = (Form_pg_proc) GETSTRUCT(tup);
1254 
1255  /* Permission check: must own function */
1256  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1258  NameListToString(stmt->func->objname));
1259 
1260  if (procForm->proisagg)
1261  ereport(ERROR,
1262  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1263  errmsg("\"%s\" is an aggregate function",
1264  NameListToString(stmt->func->objname))));
1265 
1266  is_procedure = (procForm->prorettype == InvalidOid);
1267 
1268  /* Examine requested actions. */
1269  foreach(l, stmt->actions)
1270  {
1271  DefElem *defel = (DefElem *) lfirst(l);
1272 
1273  if (compute_common_attribute(pstate,
1274  is_procedure,
1275  defel,
1276  &volatility_item,
1277  &strict_item,
1278  &security_def_item,
1279  &leakproof_item,
1280  &set_items,
1281  &cost_item,
1282  &rows_item,
1283  &parallel_item) == false)
1284  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1285  }
1286 
1287  if (volatility_item)
1288  procForm->provolatile = interpret_func_volatility(volatility_item);
1289  if (strict_item)
1290  procForm->proisstrict = intVal(strict_item->arg);
1291  if (security_def_item)
1292  procForm->prosecdef = intVal(security_def_item->arg);
1293  if (leakproof_item)
1294  {
1295  procForm->proleakproof = intVal(leakproof_item->arg);
1296  if (procForm->proleakproof && !superuser())
1297  ereport(ERROR,
1298  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1299  errmsg("only superuser can define a leakproof function")));
1300  }
1301  if (cost_item)
1302  {
1303  procForm->procost = defGetNumeric(cost_item);
1304  if (procForm->procost <= 0)
1305  ereport(ERROR,
1306  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1307  errmsg("COST must be positive")));
1308  }
1309  if (rows_item)
1310  {
1311  procForm->prorows = defGetNumeric(rows_item);
1312  if (procForm->prorows <= 0)
1313  ereport(ERROR,
1314  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1315  errmsg("ROWS must be positive")));
1316  if (!procForm->proretset)
1317  ereport(ERROR,
1318  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1319  errmsg("ROWS is not applicable when function does not return a set")));
1320  }
1321  if (set_items)
1322  {
1323  Datum datum;
1324  bool isnull;
1325  ArrayType *a;
1326  Datum repl_val[Natts_pg_proc];
1327  bool repl_null[Natts_pg_proc];
1328  bool repl_repl[Natts_pg_proc];
1329 
1330  /* extract existing proconfig setting */
1331  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1332  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1333 
1334  /* update according to each SET or RESET item, left to right */
1335  a = update_proconfig_value(a, set_items);
1336 
1337  /* update the tuple */
1338  memset(repl_repl, false, sizeof(repl_repl));
1339  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1340 
1341  if (a == NULL)
1342  {
1343  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1344  repl_null[Anum_pg_proc_proconfig - 1] = true;
1345  }
1346  else
1347  {
1348  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1349  repl_null[Anum_pg_proc_proconfig - 1] = false;
1350  }
1351 
1352  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1353  repl_val, repl_null, repl_repl);
1354  }
1355  if (parallel_item)
1356  procForm->proparallel = interpret_func_parallel(parallel_item);
1357 
1358  /* Do the update */
1359  CatalogTupleUpdate(rel, &tup->t_self, tup);
1360 
1362 
1363  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1364 
1365  heap_close(rel, NoLock);
1366  heap_freetuple(tup);
1367 
1368  return address;
1369 }
#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:467
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
#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
#define Natts_pg_proc
Definition: pg_proc.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2783
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2019
#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:566
Node * arg
Definition: parsenodes.h:720
char * NameListToString(List *names)
Definition: namespace.c:3063
uintptr_t Datum
Definition: postgres.h:372
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:609
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:2784
#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:719
#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:4682
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:584
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1828 of file functioncmds.c.

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

Referenced by CreateTransform().

1829 {
1830  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1831  ereport(ERROR,
1832  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1833  errmsg("transform function must not be volatile")));
1834  if (procstruct->proisagg)
1835  ereport(ERROR,
1836  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1837  errmsg("transform function must not be an aggregate function")));
1838  if (procstruct->proiswindow)
1839  ereport(ERROR,
1840  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1841  errmsg("transform function must not be a window function")));
1842  if (procstruct->proretset)
1843  ereport(ERROR,
1844  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1845  errmsg("transform function must not return a set")));
1846  if (procstruct->pronargs != 1)
1847  ereport(ERROR,
1848  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1849  errmsg("transform function must take one argument")));
1850  if (procstruct->proargtypes.values[0] != INTERNALOID)
1851  ereport(ERROR,
1852  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1853  errmsg("first argument of transform function must be type %s",
1854  "internal")));
1855 }
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:5539
#define INTERNALOID
Definition: pg_type.h:698
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ compute_attributes_sql_style()

static void compute_attributes_sql_style ( 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 639 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().

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

◆ compute_attributes_with_style()

static void compute_attributes_with_style ( ParseState pstate,
bool  is_procedure,
List parameters,
bool isStrict_p,
char *  volatility_p 
)
static

Definition at line 806 of file functioncmds.c.

References defGetBoolean(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, lfirst, DefElem::location, parser_errposition(), pg_strcasecmp(), PROVOLATILE_IMMUTABLE, and WARNING.

Referenced by CreateFunction().

807 {
808  ListCell *pl;
809 
810  foreach(pl, parameters)
811  {
812  DefElem *param = (DefElem *) lfirst(pl);
813 
814  if (pg_strcasecmp(param->defname, "isstrict") == 0)
815  {
816  if (is_procedure)
817  ereport(ERROR,
818  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
819  errmsg("invalid attribute in procedure definition"),
820  parser_errposition(pstate, param->location)));
821  *isStrict_p = defGetBoolean(param);
822  }
823  else if (pg_strcasecmp(param->defname, "iscachable") == 0)
824  {
825  /* obsolete spelling of isImmutable */
826  if (is_procedure)
827  ereport(ERROR,
828  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
829  errmsg("invalid attribute in procedure definition"),
830  parser_errposition(pstate, param->location)));
831  if (defGetBoolean(param))
832  *volatility_p = PROVOLATILE_IMMUTABLE;
833  }
834  else
836  (errcode(ERRCODE_SYNTAX_ERROR),
837  errmsg("unrecognized function attribute \"%s\" ignored",
838  param->defname),
839  parser_errposition(pstate, param->location)));
840  }
841 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5537
int errcode(int sqlerrcode)
Definition: elog.c:575
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ERROR
Definition: elog.h:43
int location
Definition: parsenodes.h:722
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define lfirst(lc)
Definition: pg_list.h:106
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:719

◆ 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 467 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_attributes_sql_style().

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

◆ compute_return_type()

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

Definition at line 85 of file functioncmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, 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, ObjectAddress::objectId, OidIsValid, pg_namespace_aclcheck(), pg_type_aclcheck(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, SQLlanguageId, TypeNameToString(), TypeShellMake(), typeTypeId(), and TypeName::typmods.

Referenced by CreateFunction().

87 {
88  Oid rettype;
89  Type typtup;
90  AclResult aclresult;
91 
92  typtup = LookupTypeName(NULL, returnType, NULL, false);
93 
94  if (typtup)
95  {
96  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
97  {
98  if (languageOid == SQLlanguageId)
99  ereport(ERROR,
100  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
101  errmsg("SQL function cannot return shell type %s",
102  TypeNameToString(returnType))));
103  else
104  ereport(NOTICE,
105  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
106  errmsg("return type %s is only a shell",
107  TypeNameToString(returnType))));
108  }
109  rettype = typeTypeId(typtup);
110  ReleaseSysCache(typtup);
111  }
112  else
113  {
114  char *typnam = TypeNameToString(returnType);
115  Oid namespaceId;
116  AclResult aclresult;
117  char *typname;
118  ObjectAddress address;
119 
120  /*
121  * Only C-coded functions can be I/O functions. We enforce this
122  * restriction here mainly to prevent littering the catalogs with
123  * shell types due to simple typos in user-defined function
124  * definitions.
125  */
126  if (languageOid != INTERNALlanguageId &&
127  languageOid != ClanguageId)
128  ereport(ERROR,
129  (errcode(ERRCODE_UNDEFINED_OBJECT),
130  errmsg("type \"%s\" does not exist", typnam)));
131 
132  /* Reject if there's typmod decoration, too */
133  if (returnType->typmods != NIL)
134  ereport(ERROR,
135  (errcode(ERRCODE_SYNTAX_ERROR),
136  errmsg("type modifier cannot be specified for shell type \"%s\"",
137  typnam)));
138 
139  /* Otherwise, go ahead and make a shell type */
140  ereport(NOTICE,
141  (errcode(ERRCODE_UNDEFINED_OBJECT),
142  errmsg("type \"%s\" is not yet defined", typnam),
143  errdetail("Creating a shell type definition.")));
144  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
145  &typname);
146  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
147  ACL_CREATE);
148  if (aclresult != ACLCHECK_OK)
150  get_namespace_name(namespaceId));
151  address = TypeShellMake(typname, namespaceId, GetUserId());
152  rettype = address.objectId;
153  Assert(OidIsValid(rettype));
154  }
155 
156  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
157  if (aclresult != ACLCHECK_OK)
158  aclcheck_error_type(aclresult, rettype);
159 
160  *prorettype_p = rettype;
161  *returnsSet_p = returnType->setof;
162 }
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:576
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#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:3066
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
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:670
int errmsg(const char *fmt,...)
Definition: elog.c:797
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4592
Oid typeTypeId(Type tp)
Definition: parse_type.c:571

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1463 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().

1464 {
1465  Oid sourcetypeid;
1466  Oid targettypeid;
1467  char sourcetyptype;
1468  char targettyptype;
1469  Oid funcid;
1470  Oid castid;
1471  int nargs;
1472  char castcontext;
1473  char castmethod;
1474  Relation relation;
1475  HeapTuple tuple;
1477  bool nulls[Natts_pg_cast];
1478  ObjectAddress myself,
1479  referenced;
1480  AclResult aclresult;
1481 
1482  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1483  targettypeid = typenameTypeId(NULL, stmt->targettype);
1484  sourcetyptype = get_typtype(sourcetypeid);
1485  targettyptype = get_typtype(targettypeid);
1486 
1487  /* No pseudo-types allowed */
1488  if (sourcetyptype == TYPTYPE_PSEUDO)
1489  ereport(ERROR,
1490  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1491  errmsg("source data type %s is a pseudo-type",
1492  TypeNameToString(stmt->sourcetype))));
1493 
1494  if (targettyptype == TYPTYPE_PSEUDO)
1495  ereport(ERROR,
1496  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1497  errmsg("target data type %s is a pseudo-type",
1498  TypeNameToString(stmt->targettype))));
1499 
1500  /* Permission check */
1501  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1502  && !pg_type_ownercheck(targettypeid, GetUserId()))
1503  ereport(ERROR,
1504  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1505  errmsg("must be owner of type %s or type %s",
1506  format_type_be(sourcetypeid),
1507  format_type_be(targettypeid))));
1508 
1509  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1510  if (aclresult != ACLCHECK_OK)
1511  aclcheck_error_type(aclresult, sourcetypeid);
1512 
1513  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1514  if (aclresult != ACLCHECK_OK)
1515  aclcheck_error_type(aclresult, targettypeid);
1516 
1517  /* Domains are allowed for historical reasons, but we warn */
1518  if (sourcetyptype == TYPTYPE_DOMAIN)
1519  ereport(WARNING,
1520  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1521  errmsg("cast will be ignored because the source data type is a domain")));
1522 
1523  else if (targettyptype == TYPTYPE_DOMAIN)
1524  ereport(WARNING,
1525  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1526  errmsg("cast will be ignored because the target data type is a domain")));
1527 
1528  /* Determine the cast method */
1529  if (stmt->func != NULL)
1530  castmethod = COERCION_METHOD_FUNCTION;
1531  else if (stmt->inout)
1532  castmethod = COERCION_METHOD_INOUT;
1533  else
1534  castmethod = COERCION_METHOD_BINARY;
1535 
1536  if (castmethod == COERCION_METHOD_FUNCTION)
1537  {
1538  Form_pg_proc procstruct;
1539 
1540  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1541 
1542  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1543  if (!HeapTupleIsValid(tuple))
1544  elog(ERROR, "cache lookup failed for function %u", funcid);
1545 
1546  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1547  nargs = procstruct->pronargs;
1548  if (nargs < 1 || nargs > 3)
1549  ereport(ERROR,
1550  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1551  errmsg("cast function must take one to three arguments")));
1552  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1553  ereport(ERROR,
1554  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1555  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1556  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1557  ereport(ERROR,
1558  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1559  errmsg("second argument of cast function must be type %s",
1560  "integer")));
1561  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1562  ereport(ERROR,
1563  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1564  errmsg("third argument of cast function must be type %s",
1565  "boolean")));
1566  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1567  ereport(ERROR,
1568  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1569  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1570 
1571  /*
1572  * Restricting the volatility of a cast function may or may not be a
1573  * good idea in the abstract, but it definitely breaks many old
1574  * user-defined types. Disable this check --- tgl 2/1/03
1575  */
1576 #ifdef NOT_USED
1577  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1578  ereport(ERROR,
1579  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1580  errmsg("cast function must not be volatile")));
1581 #endif
1582  if (procstruct->proisagg)
1583  ereport(ERROR,
1584  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1585  errmsg("cast function must not be an aggregate function")));
1586  if (procstruct->proiswindow)
1587  ereport(ERROR,
1588  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1589  errmsg("cast function must not be a window function")));
1590  if (procstruct->proretset)
1591  ereport(ERROR,
1592  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1593  errmsg("cast function must not return a set")));
1594 
1595  ReleaseSysCache(tuple);
1596  }
1597  else
1598  {
1599  funcid = InvalidOid;
1600  nargs = 0;
1601  }
1602 
1603  if (castmethod == COERCION_METHOD_BINARY)
1604  {
1605  int16 typ1len;
1606  int16 typ2len;
1607  bool typ1byval;
1608  bool typ2byval;
1609  char typ1align;
1610  char typ2align;
1611 
1612  /*
1613  * Must be superuser to create binary-compatible casts, since
1614  * erroneous casts can easily crash the backend.
1615  */
1616  if (!superuser())
1617  ereport(ERROR,
1618  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1619  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1620 
1621  /*
1622  * Also, insist that the types match as to size, alignment, and
1623  * pass-by-value attributes; this provides at least a crude check that
1624  * they have similar representations. A pair of types that fail this
1625  * test should certainly not be equated.
1626  */
1627  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1628  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1629  if (typ1len != typ2len ||
1630  typ1byval != typ2byval ||
1631  typ1align != typ2align)
1632  ereport(ERROR,
1633  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1634  errmsg("source and target data types are not physically compatible")));
1635 
1636  /*
1637  * We know that composite, enum and array types are never binary-
1638  * compatible with each other. They all have OIDs embedded in them.
1639  *
1640  * Theoretically you could build a user-defined base type that is
1641  * binary-compatible with a composite, enum, or array type. But we
1642  * disallow that too, as in practice such a cast is surely a mistake.
1643  * You can always work around that by writing a cast function.
1644  */
1645  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1646  targettyptype == TYPTYPE_COMPOSITE)
1647  ereport(ERROR,
1648  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1649  errmsg("composite data types are not binary-compatible")));
1650 
1651  if (sourcetyptype == TYPTYPE_ENUM ||
1652  targettyptype == TYPTYPE_ENUM)
1653  ereport(ERROR,
1654  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1655  errmsg("enum data types are not binary-compatible")));
1656 
1657  if (OidIsValid(get_element_type(sourcetypeid)) ||
1658  OidIsValid(get_element_type(targettypeid)))
1659  ereport(ERROR,
1660  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1661  errmsg("array data types are not binary-compatible")));
1662 
1663  /*
1664  * We also disallow creating binary-compatibility casts involving
1665  * domains. Casting from a domain to its base type is already
1666  * allowed, and casting the other way ought to go through domain
1667  * coercion to permit constraint checking. Again, if you're intent on
1668  * having your own semantics for that, create a no-op cast function.
1669  *
1670  * NOTE: if we were to relax this, the above checks for composites
1671  * etc. would have to be modified to look through domains to their
1672  * base types.
1673  */
1674  if (sourcetyptype == TYPTYPE_DOMAIN ||
1675  targettyptype == TYPTYPE_DOMAIN)
1676  ereport(ERROR,
1677  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1678  errmsg("domain data types must not be marked binary-compatible")));
1679  }
1680 
1681  /*
1682  * Allow source and target types to be same only for length coercion
1683  * functions. We assume a multi-arg function does length coercion.
1684  */
1685  if (sourcetypeid == targettypeid && nargs < 2)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1688  errmsg("source data type and target data type are the same")));
1689 
1690  /* convert CoercionContext enum to char value for castcontext */
1691  switch (stmt->context)
1692  {
1693  case COERCION_IMPLICIT:
1694  castcontext = COERCION_CODE_IMPLICIT;
1695  break;
1696  case COERCION_ASSIGNMENT:
1697  castcontext = COERCION_CODE_ASSIGNMENT;
1698  break;
1699  case COERCION_EXPLICIT:
1700  castcontext = COERCION_CODE_EXPLICIT;
1701  break;
1702  default:
1703  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1704  castcontext = 0; /* keep compiler quiet */
1705  break;
1706  }
1707 
1709 
1710  /*
1711  * Check for duplicate. This is just to give a friendly error message,
1712  * the unique index would catch it anyway (so no need to sweat about race
1713  * conditions).
1714  */
1716  ObjectIdGetDatum(sourcetypeid),
1717  ObjectIdGetDatum(targettypeid));
1718  if (HeapTupleIsValid(tuple))
1719  ereport(ERROR,
1721  errmsg("cast from type %s to type %s already exists",
1722  format_type_be(sourcetypeid),
1723  format_type_be(targettypeid))));
1724 
1725  /* ready to go */
1726  values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1727  values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1728  values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1729  values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1730  values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1731 
1732  MemSet(nulls, false, sizeof(nulls));
1733 
1734  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1735 
1736  castid = CatalogTupleInsert(relation, tuple);
1737 
1738  /* make dependency entries */
1739  myself.classId = CastRelationId;
1740  myself.objectId = castid;
1741  myself.objectSubId = 0;
1742 
1743  /* dependency on source type */
1744  referenced.classId = TypeRelationId;
1745  referenced.objectId = sourcetypeid;
1746  referenced.objectSubId = 0;
1747  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1748 
1749  /* dependency on target type */
1750  referenced.classId = TypeRelationId;
1751  referenced.objectId = targettypeid;
1752  referenced.objectSubId = 0;
1753  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1754 
1755  /* dependency on function */
1756  if (OidIsValid(funcid))
1757  {
1758  referenced.classId = ProcedureRelationId;
1759  referenced.objectId = funcid;
1760  referenced.objectSubId = 0;
1761  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1762  }
1763 
1764  /* dependency on extension */
1765  recordDependencyOnCurrentExtension(&myself, false);
1766 
1767  /* Post creation hook for new cast */
1769 
1770  heap_freetuple(tuple);
1771 
1772  heap_close(relation, RowExclusiveLock);
1773 
1774  return myself;
1775 }
signed short int16
Definition: c.h:283
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
TypeName * sourcetype
Definition: parsenodes.h:3295
#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:2517
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2040
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:2398
#define MemSet(start, val, len)
Definition: c.h:853
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
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:4630
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:576
#define Anum_pg_cast_castmethod
Definition: pg_cast.h:82
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#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:513
#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:2019
CoercionContext context
Definition: parsenodes.h:3298
#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:5539
#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:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
ObjectWithArgs * func
Definition: parsenodes.h:3297
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:422
#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:3296
#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:4592
#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 914 of file functioncmds.c.

References ACL_CREATE, ACL_KIND_LANGUAGE, ACL_KIND_NAMESPACE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, Assert, castNode, ClanguageId, compute_attributes_sql_style(), compute_attributes_with_style(), 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_PROCEDURE, 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(), VOIDOID, and CreateFunctionStmt::withClause.

Referenced by ProcessUtilitySlow().

915 {
916  char *probin_str;
917  char *prosrc_str;
918  Oid prorettype;
919  bool returnsSet;
920  char *language;
921  Oid languageOid;
922  Oid languageValidator;
923  Node *transformDefElem = NULL;
924  char *funcname;
925  Oid namespaceId;
926  AclResult aclresult;
927  oidvector *parameterTypes;
928  ArrayType *allParameterTypes;
929  ArrayType *parameterModes;
930  ArrayType *parameterNames;
931  List *parameterDefaults;
932  Oid variadicArgType;
933  List *trftypes_list = NIL;
934  ArrayType *trftypes;
935  Oid requiredResultType;
936  bool isWindowFunc,
937  isStrict,
938  security,
939  isLeakProof;
940  char volatility;
941  ArrayType *proconfig;
942  float4 procost;
943  float4 prorows;
944  HeapTuple languageTuple;
945  Form_pg_language languageStruct;
946  List *as_clause;
947  char parallel;
948 
949  /* Convert list of names to a name and namespace */
950  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
951  &funcname);
952 
953  /* Check we have creation rights in target namespace */
954  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
955  if (aclresult != ACLCHECK_OK)
957  get_namespace_name(namespaceId));
958 
959  /* default attributes */
960  isWindowFunc = false;
961  isStrict = false;
962  security = false;
963  isLeakProof = false;
964  volatility = PROVOLATILE_VOLATILE;
965  proconfig = NULL;
966  procost = -1; /* indicates not set */
967  prorows = -1; /* indicates not set */
968  parallel = PROPARALLEL_UNSAFE;
969 
970  /* override attributes from explicit list */
972  stmt->is_procedure,
973  stmt->options,
974  &as_clause, &language, &transformDefElem,
975  &isWindowFunc, &volatility,
976  &isStrict, &security, &isLeakProof,
977  &proconfig, &procost, &prorows, &parallel);
978 
979  /* Look up the language and validate permissions */
980  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
981  if (!HeapTupleIsValid(languageTuple))
982  ereport(ERROR,
983  (errcode(ERRCODE_UNDEFINED_OBJECT),
984  errmsg("language \"%s\" does not exist", language),
985  (PLTemplateExists(language) ?
986  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
987 
988  languageOid = HeapTupleGetOid(languageTuple);
989  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
990 
991  if (languageStruct->lanpltrusted)
992  {
993  /* if trusted language, need USAGE privilege */
994  AclResult aclresult;
995 
996  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
997  if (aclresult != ACLCHECK_OK)
999  NameStr(languageStruct->lanname));
1000  }
1001  else
1002  {
1003  /* if untrusted language, must be superuser */
1004  if (!superuser())
1006  NameStr(languageStruct->lanname));
1007  }
1008 
1009  languageValidator = languageStruct->lanvalidator;
1010 
1011  ReleaseSysCache(languageTuple);
1012 
1013  /*
1014  * Only superuser is allowed to create leakproof functions because
1015  * leakproof functions can see tuples which have not yet been filtered out
1016  * by security barrier views or row level security policies.
1017  */
1018  if (isLeakProof && !superuser())
1019  ereport(ERROR,
1020  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1021  errmsg("only superuser can define a leakproof function")));
1022 
1023  if (transformDefElem)
1024  {
1025  ListCell *lc;
1026 
1027  foreach(lc, castNode(List, transformDefElem))
1028  {
1029  Oid typeid = typenameTypeId(NULL,
1030  lfirst_node(TypeName, lc));
1031  Oid elt = get_base_element_type(typeid);
1032 
1033  typeid = elt ? elt : typeid;
1034 
1035  get_transform_oid(typeid, languageOid, false);
1036  trftypes_list = lappend_oid(trftypes_list, typeid);
1037  }
1038  }
1039 
1040  /*
1041  * Convert remaining parameters of CREATE to form wanted by
1042  * ProcedureCreate.
1043  */
1045  stmt->parameters,
1046  languageOid,
1048  &parameterTypes,
1049  &allParameterTypes,
1050  &parameterModes,
1051  &parameterNames,
1052  &parameterDefaults,
1053  &variadicArgType,
1054  &requiredResultType);
1055 
1056  if (stmt->is_procedure)
1057  {
1058  Assert(!stmt->returnType);
1059 
1060  prorettype = InvalidOid;
1061  returnsSet = false;
1062  }
1063  else if (stmt->returnType)
1064  {
1065  /* explicit RETURNS clause */
1066  compute_return_type(stmt->returnType, languageOid,
1067  &prorettype, &returnsSet);
1068  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1069  ereport(ERROR,
1070  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1071  errmsg("function result type must be %s because of OUT parameters",
1072  format_type_be(requiredResultType))));
1073  }
1074  else if (OidIsValid(requiredResultType))
1075  {
1076  /* default RETURNS clause from OUT parameters */
1077  prorettype = requiredResultType;
1078  returnsSet = false;
1079  }
1080  else
1081  {
1082  ereport(ERROR,
1083  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1084  errmsg("function result type must be specified")));
1085  /* Alternative possibility: default to RETURNS VOID */
1086  prorettype = VOIDOID;
1087  returnsSet = false;
1088  }
1089 
1090  if (list_length(trftypes_list) > 0)
1091  {
1092  ListCell *lc;
1093  Datum *arr;
1094  int i;
1095 
1096  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1097  i = 0;
1098  foreach(lc, trftypes_list)
1099  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1100  trftypes = construct_array(arr, list_length(trftypes_list),
1101  OIDOID, sizeof(Oid), true, 'i');
1102  }
1103  else
1104  {
1105  /* store SQL NULL instead of empty array */
1106  trftypes = NULL;
1107  }
1108 
1109  compute_attributes_with_style(pstate, stmt->is_procedure, stmt->withClause, &isStrict, &volatility);
1110 
1111  interpret_AS_clause(languageOid, language, funcname, as_clause,
1112  &prosrc_str, &probin_str);
1113 
1114  /*
1115  * Set default values for COST and ROWS depending on other parameters;
1116  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1117  * values, keep it in sync if you change them.
1118  */
1119  if (procost < 0)
1120  {
1121  /* SQL and PL-language functions are assumed more expensive */
1122  if (languageOid == INTERNALlanguageId ||
1123  languageOid == ClanguageId)
1124  procost = 1;
1125  else
1126  procost = 100;
1127  }
1128  if (prorows < 0)
1129  {
1130  if (returnsSet)
1131  prorows = 1000;
1132  else
1133  prorows = 0; /* dummy value if not returnsSet */
1134  }
1135  else if (!returnsSet)
1136  ereport(ERROR,
1137  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1138  errmsg("ROWS is not applicable when function does not return a set")));
1139 
1140  /*
1141  * And now that we have all the parameters, and know we're permitted to do
1142  * so, go ahead and create the function.
1143  */
1144  return ProcedureCreate(funcname,
1145  namespaceId,
1146  stmt->replace,
1147  returnsSet,
1148  prorettype,
1149  GetUserId(),
1150  languageOid,
1151  languageValidator,
1152  prosrc_str, /* converted to text later */
1153  probin_str, /* converted to text later */
1154  false, /* not an aggregate */
1155  isWindowFunc,
1156  security,
1157  isLeakProof,
1158  isStrict,
1159  volatility,
1160  parallel,
1161  parameterTypes,
1162  PointerGetDatum(allParameterTypes),
1163  PointerGetDatum(parameterModes),
1164  PointerGetDatum(parameterNames),
1165  parameterDefaults,
1166  PointerGetDatum(trftypes),
1167  PointerGetDatum(proconfig),
1168  procost,
1169  prorows);
1170 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:526
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:581
#define OIDOID
Definition: pg_type.h:328
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
#define PointerGetDatum(X)
Definition: postgres.h:562
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:85
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:512
#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:94
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:854
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:576
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
static void compute_attributes_with_style(ParseState *pstate, bool is_procedure, List *parameters, bool *isStrict_p, char *volatility_p)
Definition: functioncmds.c:806
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4516
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
#define VOIDOID
Definition: pg_type.h:690
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:3066
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5548
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5539
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
float float4
Definition: c.h:428
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
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:670
TypeName * returnType
Definition: parsenodes.h:2755
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:181
static void compute_attributes_sql_style(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:639
static int list_length(const List *l)
Definition: pg_list.h:89
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2590
FormData_pg_language * Form_pg_language
Definition: pg_language.h:51
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:547
#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 1862 of file functioncmds.c.

References ACL_EXECUTE, ACL_KIND_LANGUAGE, ACL_KIND_PROC, 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, 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().

1863 {
1864  Oid typeid;
1865  char typtype;
1866  Oid langid;
1867  Oid fromsqlfuncid;
1868  Oid tosqlfuncid;
1869  AclResult aclresult;
1870  Form_pg_proc procstruct;
1872  bool nulls[Natts_pg_transform];
1873  bool replaces[Natts_pg_transform];
1874  Oid transformid;
1875  HeapTuple tuple;
1876  HeapTuple newtuple;
1877  Relation relation;
1878  ObjectAddress myself,
1879  referenced;
1880  bool is_replace;
1881 
1882  /*
1883  * Get the type
1884  */
1885  typeid = typenameTypeId(NULL, stmt->type_name);
1886  typtype = get_typtype(typeid);
1887 
1888  if (typtype == TYPTYPE_PSEUDO)
1889  ereport(ERROR,
1890  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1891  errmsg("data type %s is a pseudo-type",
1892  TypeNameToString(stmt->type_name))));
1893 
1894  if (typtype == TYPTYPE_DOMAIN)
1895  ereport(ERROR,
1896  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1897  errmsg("data type %s is a domain",
1898  TypeNameToString(stmt->type_name))));
1899 
1900  if (!pg_type_ownercheck(typeid, GetUserId()))
1902 
1903  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1904  if (aclresult != ACLCHECK_OK)
1905  aclcheck_error_type(aclresult, typeid);
1906 
1907  /*
1908  * Get the language
1909  */
1910  langid = get_language_oid(stmt->lang, false);
1911 
1912  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1913  if (aclresult != ACLCHECK_OK)
1914  aclcheck_error(aclresult, ACL_KIND_LANGUAGE, stmt->lang);
1915 
1916  /*
1917  * Get the functions
1918  */
1919  if (stmt->fromsql)
1920  {
1921  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1922 
1923  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1925 
1926  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1927  if (aclresult != ACLCHECK_OK)
1929 
1930  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1931  if (!HeapTupleIsValid(tuple))
1932  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1933  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1934  if (procstruct->prorettype != INTERNALOID)
1935  ereport(ERROR,
1936  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1937  errmsg("return data type of FROM SQL function must be %s",
1938  "internal")));
1939  check_transform_function(procstruct);
1940  ReleaseSysCache(tuple);
1941  }
1942  else
1943  fromsqlfuncid = InvalidOid;
1944 
1945  if (stmt->tosql)
1946  {
1947  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1948 
1949  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1951 
1952  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1953  if (aclresult != ACLCHECK_OK)
1955 
1956  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1957  if (!HeapTupleIsValid(tuple))
1958  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1959  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1960  if (procstruct->prorettype != typeid)
1961  ereport(ERROR,
1962  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1963  errmsg("return data type of TO SQL function must be the transform data type")));
1964  check_transform_function(procstruct);
1965  ReleaseSysCache(tuple);
1966  }
1967  else
1968  tosqlfuncid = InvalidOid;
1969 
1970  /*
1971  * Ready to go
1972  */
1973  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1974  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1975  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1976  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1977 
1978  MemSet(nulls, false, sizeof(nulls));
1979 
1981 
1982  tuple = SearchSysCache2(TRFTYPELANG,
1983  ObjectIdGetDatum(typeid),
1984  ObjectIdGetDatum(langid));
1985  if (HeapTupleIsValid(tuple))
1986  {
1987  if (!stmt->replace)
1988  ereport(ERROR,
1990  errmsg("transform for type %s language \"%s\" already exists",
1991  format_type_be(typeid),
1992  stmt->lang)));
1993 
1994  MemSet(replaces, false, sizeof(replaces));
1995  replaces[Anum_pg_transform_trffromsql - 1] = true;
1996  replaces[Anum_pg_transform_trftosql - 1] = true;
1997 
1998  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1999  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2000 
2001  transformid = HeapTupleGetOid(tuple);
2002  ReleaseSysCache(tuple);
2003  is_replace = true;
2004  }
2005  else
2006  {
2007  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
2008  transformid = CatalogTupleInsert(relation, newtuple);
2009  is_replace = false;
2010  }
2011 
2012  if (is_replace)
2013  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
2014 
2015  /* make dependency entries */
2016  myself.classId = TransformRelationId;
2017  myself.objectId = transformid;
2018  myself.objectSubId = 0;
2019 
2020  /* dependency on language */
2021  referenced.classId = LanguageRelationId;
2022  referenced.objectId = langid;
2023  referenced.objectSubId = 0;
2024  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2025 
2026  /* dependency on type */
2027  referenced.classId = TypeRelationId;
2028  referenced.objectId = typeid;
2029  referenced.objectSubId = 0;
2030  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2031 
2032  /* dependencies on functions */
2033  if (OidIsValid(fromsqlfuncid))
2034  {
2035  referenced.classId = ProcedureRelationId;
2036  referenced.objectId = fromsqlfuncid;
2037  referenced.objectSubId = 0;
2038  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2039  }
2040  if (OidIsValid(tosqlfuncid))
2041  {
2042  referenced.classId = ProcedureRelationId;
2043  referenced.objectId = tosqlfuncid;
2044  referenced.objectSubId = 0;
2045  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2046  }
2047 
2048  /* dependency on extension */
2049  recordDependencyOnCurrentExtension(&myself, is_replace);
2050 
2051  /* Post creation hook for new transform */
2053 
2054  heap_freetuple(newtuple);
2055 
2056  heap_close(relation, RowExclusiveLock);
2057 
2058  return myself;
2059 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
ObjectWithArgs * tosql
Definition: parsenodes.h:3313
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:2398
#define MemSet(start, val, len)
Definition: c.h:853
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
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:4630
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:576
#define Anum_pg_transform_trftosql
Definition: pg_transform.h:45
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4516
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2019
#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:372
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:3312
#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:3310
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:4504
#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:4592
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:4682
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ DropCastById()

void DropCastById ( Oid  castOid)

Definition at line 1801 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().

1802 {
1803  Relation relation;
1804  ScanKeyData scankey;
1805  SysScanDesc scan;
1806  HeapTuple tuple;
1807 
1809 
1810  ScanKeyInit(&scankey,
1812  BTEqualStrategyNumber, F_OIDEQ,
1813  ObjectIdGetDatum(castOid));
1814  scan = systable_beginscan(relation, CastOidIndexId, true,
1815  NULL, 1, &scankey);
1816 
1817  tuple = systable_getnext(scan);
1818  if (!HeapTupleIsValid(tuple))
1819  elog(ERROR, "could not find tuple for cast %u", castOid);
1820  CatalogTupleDelete(relation, &tuple->t_self);
1821 
1822  systable_endscan(scan);
1823  heap_close(relation, RowExclusiveLock);
1824 }
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:513
#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 2087 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().

2088 {
2089  Relation relation;
2090  ScanKeyData scankey;
2091  SysScanDesc scan;
2092  HeapTuple tuple;
2093 
2095 
2096  ScanKeyInit(&scankey,
2098  BTEqualStrategyNumber, F_OIDEQ,
2099  ObjectIdGetDatum(transformOid));
2100  scan = systable_beginscan(relation, TransformOidIndexId, true,
2101  NULL, 1, &scankey);
2102 
2103  tuple = systable_getnext(scan);
2104  if (!HeapTupleIsValid(tuple))
2105  elog(ERROR, "could not find tuple for transform %u", transformOid);
2106  CatalogTupleDelete(relation, &tuple->t_self);
2107 
2108  systable_endscan(scan);
2109  heap_close(relation, RowExclusiveLock);
2110 }
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:513
#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 
)

Definition at line 2241 of file functioncmds.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, FuncCall::args, FuncExpr::args, castNode, CreateExecutorState(), CreateStandaloneExprContext(), ereport, errcode(), errmsg_plural(), ERROR, ExecEvalExprSwitchContext(), ExecPrepareExpr(), EXPR_KIND_CALL, fmgr_info(), FreeExecutorState(), FUNC_MAX_ARGS, CallStmt::funccall, FuncExpr::funcid, FuncCall::funcname, FunctionCallInvoke, get_func_name(), GetUserId(), i, InitFunctionCallInfoData, FuncExpr::inputcollid, InvokeFunctionExecuteHook, lappend(), lfirst, list_length(), FuncCall::location, NIL, ParseState::p_last_srf, ParseFuncOrColumn(), pg_proc_aclcheck(), transformExpr(), and val.

Referenced by standard_ProcessUtility().

2242 {
2243  List *targs;
2244  ListCell *lc;
2245  Node *node;
2246  FuncExpr *fexpr;
2247  int nargs;
2248  int i;
2249  AclResult aclresult;
2250  FmgrInfo flinfo;
2251  FunctionCallInfoData fcinfo;
2252 
2253  targs = NIL;
2254  foreach(lc, stmt->funccall->args)
2255  {
2256  targs = lappend(targs, transformExpr(pstate,
2257  (Node *) lfirst(lc),
2258  EXPR_KIND_CALL));
2259  }
2260 
2261  node = ParseFuncOrColumn(pstate,
2262  stmt->funccall->funcname,
2263  targs,
2264  pstate->p_last_srf,
2265  stmt->funccall,
2266  true,
2267  stmt->funccall->location);
2268 
2269  fexpr = castNode(FuncExpr, node);
2270 
2271  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2272  if (aclresult != ACLCHECK_OK)
2273  aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(fexpr->funcid));
2275 
2276  nargs = list_length(fexpr->args);
2277 
2278  /* safety check; see ExecInitFunc() */
2279  if (nargs > FUNC_MAX_ARGS)
2280  ereport(ERROR,
2281  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2282  errmsg_plural("cannot pass more than %d argument to a procedure",
2283  "cannot pass more than %d arguments to a procedure",
2284  FUNC_MAX_ARGS,
2285  FUNC_MAX_ARGS)));
2286 
2287  fmgr_info(fexpr->funcid, &flinfo);
2288  InitFunctionCallInfoData(fcinfo, &flinfo, nargs, fexpr->inputcollid, NULL, NULL);
2289 
2290  i = 0;
2291  foreach (lc, fexpr->args)
2292  {
2293  EState *estate;
2294  ExprState *exprstate;
2295  ExprContext *econtext;
2296  Datum val;
2297  bool isnull;
2298 
2299  estate = CreateExecutorState();
2300  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2301  econtext = CreateStandaloneExprContext();
2302  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2303  FreeExecutorState(estate);
2304 
2305  fcinfo.arg[i] = val;
2306  fcinfo.argnull[i] = isnull;
2307 
2308  i++;
2309  }
2310 
2311  FunctionCallInvoke(&fcinfo);
2312 }
#define NIL
Definition: pg_list.h:69
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:298
Definition: fmgr.h:56
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:291
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:581
FuncCall * funccall
Definition: parsenodes.h:2815
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:512
int errcode(int sqlerrcode)
Definition: elog.c:575
int location
Definition: parsenodes.h:358
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:437
#define FUNC_MAX_ARGS
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
Oid funcid
Definition: primnodes.h:449
#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:1412
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
EState * CreateExecutorState(void)
Definition: execUtils.c:81
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
List * lappend(List *list, void *datum)
Definition: list.c:128
AclResult
Definition: acl.h:178
Node * p_last_srf
Definition: parse_node.h:205
uintptr_t Datum
Definition: postgres.h:372
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
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:4504
int i
List * funcname
Definition: parsenodes.h:349
Definition: pg_list.h:45
long val
Definition: informix.c:689

◆ ExecuteDoStmt()

void ExecuteDoStmt ( DoStmt stmt)

Definition at line 2141 of file functioncmds.c.

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

Referenced by standard_ProcessUtility().

2142 {
2144  ListCell *arg;
2145  DefElem *as_item = NULL;
2146  DefElem *language_item = NULL;
2147  char *language;
2148  Oid laninline;
2149  HeapTuple languageTuple;
2150  Form_pg_language languageStruct;
2151 
2152  /* Process options we got from gram.y */
2153  foreach(arg, stmt->args)
2154  {
2155  DefElem *defel = (DefElem *) lfirst(arg);
2156 
2157  if (strcmp(defel->defname, "as") == 0)
2158  {
2159  if (as_item)
2160  ereport(ERROR,
2161  (errcode(ERRCODE_SYNTAX_ERROR),
2162  errmsg("conflicting or redundant options")));
2163  as_item = defel;
2164  }
2165  else if (strcmp(defel->defname, "language") == 0)
2166  {
2167  if (language_item)
2168  ereport(ERROR,
2169  (errcode(ERRCODE_SYNTAX_ERROR),
2170  errmsg("conflicting or redundant options")));
2171  language_item = defel;
2172  }
2173  else
2174  elog(ERROR, "option \"%s\" not recognized",
2175  defel->defname);
2176  }
2177 
2178  if (as_item)
2179  codeblock->source_text = strVal(as_item->arg);
2180  else
2181  ereport(ERROR,
2182  (errcode(ERRCODE_SYNTAX_ERROR),
2183  errmsg("no inline code specified")));
2184 
2185  /* if LANGUAGE option wasn't specified, use the default */
2186  if (language_item)
2187  language = strVal(language_item->arg);
2188  else
2189  language = "plpgsql";
2190 
2191  /* Look up the language and validate permissions */
2192  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2193  if (!HeapTupleIsValid(languageTuple))
2194  ereport(ERROR,
2195  (errcode(ERRCODE_UNDEFINED_OBJECT),
2196  errmsg("language \"%s\" does not exist", language),
2197  (PLTemplateExists(language) ?
2198  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
2199 
2200  codeblock->langOid = HeapTupleGetOid(languageTuple);
2201  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2202  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2203 
2204  if (languageStruct->lanpltrusted)
2205  {
2206  /* if trusted language, need USAGE privilege */
2207  AclResult aclresult;
2208 
2209  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2210  ACL_USAGE);
2211  if (aclresult != ACLCHECK_OK)
2212  aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
2213  NameStr(languageStruct->lanname));
2214  }
2215  else
2216  {
2217  /* if untrusted language, must be superuser */
2218  if (!superuser())
2220  NameStr(languageStruct->lanname));
2221  }
2222 
2223  /* get the handler function's OID */
2224  laninline = languageStruct->laninline;
2225  if (!OidIsValid(laninline))
2226  ereport(ERROR,
2227  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2228  errmsg("language \"%s\" does not support inline code execution",
2229  NameStr(languageStruct->lanname))));
2230 
2231  ReleaseSysCache(languageTuple);
2232 
2233  /* execute the inline handler */
2234  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2235 }
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:562
#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:576
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4516
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:623
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
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:560
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: parsenodes.h:2797
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:547
void * arg
char * source_text
Definition: parsenodes.h:2803
char * defname
Definition: parsenodes.h:719
#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 1784 of file functioncmds.c.

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

Referenced by get_object_address().

1785 {
1786  Oid oid;
1787 
1789  ObjectIdGetDatum(sourcetypeid),
1790  ObjectIdGetDatum(targettypeid));
1791  if (!OidIsValid(oid) && !missing_ok)
1792  ereport(ERROR,
1793  (errcode(ERRCODE_UNDEFINED_OBJECT),
1794  errmsg("cast from type %s to type %s does not exist",
1795  format_type_be(sourcetypeid),
1796  format_type_be(targettypeid))));
1797  return oid;
1798 }
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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 2069 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().

2070 {
2071  Oid oid;
2072 
2074  ObjectIdGetDatum(type_id),
2075  ObjectIdGetDatum(lang_id));
2076  if (!OidIsValid(oid) && !missing_ok)
2077  ereport(ERROR,
2078  (errcode(ERRCODE_UNDEFINED_OBJECT),
2079  errmsg("transform for type %s language \"%s\" does not exist",
2080  format_type_be(type_id),
2081  get_language_name(lang_id, false))));
2082  return oid;
2083 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1018
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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 854 of file functioncmds.c.

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

Referenced by CreateFunction().

857 {
858  Assert(as != NIL);
859 
860  if (languageOid == ClanguageId)
861  {
862  /*
863  * For "C" language, store the file name in probin and, when given,
864  * the link symbol name in prosrc. If link symbol is omitted,
865  * substitute procedure name. We also allow link symbol to be
866  * specified as "-", since that was the habit in PG versions before
867  * 8.4, and there might be dump files out there that don't translate
868  * that back to "omitted".
869  */
870  *probin_str_p = strVal(linitial(as));
871  if (list_length(as) == 1)
872  *prosrc_str_p = funcname;
873  else
874  {
875  *prosrc_str_p = strVal(lsecond(as));
876  if (strcmp(*prosrc_str_p, "-") == 0)
877  *prosrc_str_p = funcname;
878  }
879  }
880  else
881  {
882  /* Everything else wants the given string in prosrc. */
883  *prosrc_str_p = strVal(linitial(as));
884  *probin_str_p = NULL;
885 
886  if (list_length(as) != 1)
887  ereport(ERROR,
888  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
889  errmsg("only one AS item needed for language \"%s\"",
890  languageName)));
891 
892  if (languageOid == INTERNALlanguageId)
893  {
894  /*
895  * In PostgreSQL versions before 6.5, the SQL name of the created
896  * function could not be different from the internal name, and
897  * "prosrc" wasn't used. So there is code out there that does
898  * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
899  * modicum of backwards compatibility, accept an empty "prosrc"
900  * value as meaning the supplied SQL function name.
901  */
902  if (strlen(*prosrc_str_p) == 0)
903  *prosrc_str_p = funcname;
904  }
905  }
906 }
#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:670
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 584 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_attributes_sql_style().

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

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 566 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_attributes_sql_style().

567 {
568  char *str = strVal(defel->arg);
569 
570  if (strcmp(str, "immutable") == 0)
571  return PROVOLATILE_IMMUTABLE;
572  else if (strcmp(str, "stable") == 0)
573  return PROVOLATILE_STABLE;
574  else if (strcmp(str, "volatile") == 0)
575  return PROVOLATILE_VOLATILE;
576  else
577  {
578  elog(ERROR, "invalid volatility \"%s\"", str);
579  return 0; /* keep compiler quiet */
580  }
581 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5537
#define strVal(v)
Definition: value.h:54
#define ERROR
Definition: elog.h:43
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5538
Node * arg
Definition: parsenodes.h:720
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5539
#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 181 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().

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

◆ IsThereFunctionInNamespace()

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

Definition at line 2120 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().

2122 {
2123  /* check for duplicate name (more friendly than unique-index failure) */
2125  CStringGetDatum(proname),
2126  PointerGetDatum(proargtypes),
2127  ObjectIdGetDatum(nspOid)))
2128  ereport(ERROR,
2129  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2130  errmsg("function %s already exists in schema \"%s\"",
2131  funcname_signature_string(proname, pronargs,
2132  NIL, proargtypes->values),
2133  get_namespace_name(nspOid))));
2134 }
#define NIL
Definition: pg_list.h:69
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:3066
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:534
#define CStringGetDatum(X)
Definition: postgres.h:584
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1894
#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 1179 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().

1180 {
1181  Relation relation;
1182  HeapTuple tup;
1183  bool isagg;
1184 
1185  /*
1186  * Delete the pg_proc tuple.
1187  */
1189 
1190  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1191  if (!HeapTupleIsValid(tup)) /* should not happen */
1192  elog(ERROR, "cache lookup failed for function %u", funcOid);
1193 
1194  isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
1195 
1196  CatalogTupleDelete(relation, &tup->t_self);
1197 
1198  ReleaseSysCache(tup);
1199 
1200  heap_close(relation, RowExclusiveLock);
1201 
1202  /*
1203  * If there's a pg_aggregate tuple, delete that too.
1204  */
1205  if (isagg)
1206  {
1208 
1209  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1210  if (!HeapTupleIsValid(tup)) /* should not happen */
1211  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1212 
1213  CatalogTupleDelete(relation, &tup->t_self);
1214 
1215  ReleaseSysCache(tup);
1216 
1217  heap_close(relation, RowExclusiveLock);
1218  }
1219 }
#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:513
#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 1421 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().

1422 {
1423  Relation pg_proc_rel;
1424  HeapTuple tup;
1425  Form_pg_proc procForm;
1426  ObjectAddress func_address;
1427  ObjectAddress type_address;
1428 
1430 
1431  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1432  if (!HeapTupleIsValid(tup)) /* should not happen */
1433  elog(ERROR, "cache lookup failed for function %u", funcOid);
1434  procForm = (Form_pg_proc) GETSTRUCT(tup);
1435 
1436  if (argIndex < 0 || argIndex >= procForm->pronargs ||
1437  procForm->proargtypes.values[argIndex] != OPAQUEOID)
1438  elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1439 
1440  /* okay to overwrite copied tuple */
1441  procForm->proargtypes.values[argIndex] = newArgType;
1442 
1443  /* update the catalog and its indexes */
1444  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1445 
1446  heap_close(pg_proc_rel, RowExclusiveLock);
1447 
1448  /*
1449  * Also update the dependency to the new type. Opaque is a pinned type, so
1450  * there is no old dependency record for it that we would need to remove.
1451  */
1452  ObjectAddressSet(type_address, TypeRelationId, newArgType);
1453  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1454  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1455 }
#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:513
#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 1379 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().

1380 {
1381  Relation pg_proc_rel;
1382  HeapTuple tup;
1383  Form_pg_proc procForm;
1384  ObjectAddress func_address;
1385  ObjectAddress type_address;
1386 
1388 
1389  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1390  if (!HeapTupleIsValid(tup)) /* should not happen */
1391  elog(ERROR, "cache lookup failed for function %u", funcOid);
1392  procForm = (Form_pg_proc) GETSTRUCT(tup);
1393 
1394  if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1395  elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1396 
1397  /* okay to overwrite copied tuple */
1398  procForm->prorettype = newRetType;
1399 
1400  /* update the catalog and its indexes */
1401  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1402 
1403  heap_close(pg_proc_rel, RowExclusiveLock);
1404 
1405  /*
1406  * Also update the dependency to the new type. Opaque is a pinned type, so
1407  * there is no old dependency record for it that we would need to remove.
1408  */
1409  ObjectAddressSet(type_address, TypeRelationId, newRetType);
1410  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1411  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1412 }
#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:513
#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 609 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_attributes_sql_style().

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