PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "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, bool is_aggregate, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
 
static bool compute_common_attribute (ParseState *pstate, 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, 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, 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)
 

Function Documentation

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1166 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, InvokeObjectPostAlterHook, lfirst, LookupFuncWithArgs(), NameListToString(), Natts_pg_proc, NIL, NoLock, NULL, ObjectAddressSet, ObjectIdGetDatum, ObjectWithArgs::objname, pg_proc_ownercheck(), PointerGetDatum, ProcedureRelationId, PROCOID, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, and update_proconfig_value().

Referenced by ProcessUtilitySlow().

1167 {
1168  HeapTuple tup;
1169  Oid funcOid;
1170  Form_pg_proc procForm;
1171  Relation rel;
1172  ListCell *l;
1173  DefElem *volatility_item = NULL;
1174  DefElem *strict_item = NULL;
1175  DefElem *security_def_item = NULL;
1176  DefElem *leakproof_item = NULL;
1177  List *set_items = NIL;
1178  DefElem *cost_item = NULL;
1179  DefElem *rows_item = NULL;
1180  DefElem *parallel_item = NULL;
1181  ObjectAddress address;
1182 
1184 
1185  funcOid = LookupFuncWithArgs(stmt->func, false);
1186 
1187  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1188  if (!HeapTupleIsValid(tup)) /* should not happen */
1189  elog(ERROR, "cache lookup failed for function %u", funcOid);
1190 
1191  procForm = (Form_pg_proc) GETSTRUCT(tup);
1192 
1193  /* Permission check: must own function */
1194  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1196  NameListToString(stmt->func->objname));
1197 
1198  if (procForm->proisagg)
1199  ereport(ERROR,
1200  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1201  errmsg("\"%s\" is an aggregate function",
1202  NameListToString(stmt->func->objname))));
1203 
1204  /* Examine requested actions. */
1205  foreach(l, stmt->actions)
1206  {
1207  DefElem *defel = (DefElem *) lfirst(l);
1208 
1209  if (compute_common_attribute(pstate,
1210  defel,
1211  &volatility_item,
1212  &strict_item,
1213  &security_def_item,
1214  &leakproof_item,
1215  &set_items,
1216  &cost_item,
1217  &rows_item,
1218  &parallel_item) == false)
1219  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1220  }
1221 
1222  if (volatility_item)
1223  procForm->provolatile = interpret_func_volatility(volatility_item);
1224  if (strict_item)
1225  procForm->proisstrict = intVal(strict_item->arg);
1226  if (security_def_item)
1227  procForm->prosecdef = intVal(security_def_item->arg);
1228  if (leakproof_item)
1229  {
1230  procForm->proleakproof = intVal(leakproof_item->arg);
1231  if (procForm->proleakproof && !superuser())
1232  ereport(ERROR,
1233  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1234  errmsg("only superuser can define a leakproof function")));
1235  }
1236  if (cost_item)
1237  {
1238  procForm->procost = defGetNumeric(cost_item);
1239  if (procForm->procost <= 0)
1240  ereport(ERROR,
1241  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1242  errmsg("COST must be positive")));
1243  }
1244  if (rows_item)
1245  {
1246  procForm->prorows = defGetNumeric(rows_item);
1247  if (procForm->prorows <= 0)
1248  ereport(ERROR,
1249  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1250  errmsg("ROWS must be positive")));
1251  if (!procForm->proretset)
1252  ereport(ERROR,
1253  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1254  errmsg("ROWS is not applicable when function does not return a set")));
1255  }
1256  if (set_items)
1257  {
1258  Datum datum;
1259  bool isnull;
1260  ArrayType *a;
1261  Datum repl_val[Natts_pg_proc];
1262  bool repl_null[Natts_pg_proc];
1263  bool repl_repl[Natts_pg_proc];
1264 
1265  /* extract existing proconfig setting */
1266  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1267  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1268 
1269  /* update according to each SET or RESET item, left to right */
1270  a = update_proconfig_value(a, set_items);
1271 
1272  /* update the tuple */
1273  memset(repl_repl, false, sizeof(repl_repl));
1274  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1275 
1276  if (a == NULL)
1277  {
1278  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1279  repl_null[Anum_pg_proc_proconfig - 1] = true;
1280  }
1281  else
1282  {
1283  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1284  repl_null[Anum_pg_proc_proconfig - 1] = false;
1285  }
1286 
1287  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1288  repl_val, repl_null, repl_repl);
1289  }
1290  if (parallel_item)
1291  procForm->proparallel = interpret_func_parallel(parallel_item);
1292 
1293  /* Do the update */
1294  CatalogTupleUpdate(rel, &tup->t_self, tup);
1295 
1297 
1298  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1299 
1300  heap_close(rel, NoLock);
1301  heap_freetuple(tup);
1302 
1303  return address;
1304 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:283
#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:1372
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
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
Oid LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
Definition: parse_func.c:1990
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:532
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:575
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
ObjectWithArgs * func
Definition: parsenodes.h:2755
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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:165
#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
static bool compute_common_attribute(ParseState *pstate, 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:453
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:791
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4624
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:550
#define DatumGetArrayTypeP(X)
Definition: array.h:242
static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1763 of file functioncmds.c.

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

Referenced by CreateTransform().

1764 {
1765  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1766  ereport(ERROR,
1767  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1768  errmsg("transform function must not be volatile")));
1769  if (procstruct->proisagg)
1770  ereport(ERROR,
1771  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1772  errmsg("transform function must not be an aggregate function")));
1773  if (procstruct->proiswindow)
1774  ereport(ERROR,
1775  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1776  errmsg("transform function must not be a window function")));
1777  if (procstruct->proretset)
1778  ereport(ERROR,
1779  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1780  errmsg("transform function must not return a set")));
1781  if (procstruct->pronargs != 1)
1782  ereport(ERROR,
1783  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1784  errmsg("transform function must take one argument")));
1785  if (procstruct->proargtypes.values[0] != INTERNALOID)
1786  ereport(ERROR,
1787  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1788  errmsg("first argument of transform function must be type %s",
1789  "internal")));
1790 }
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:5488
#define INTERNALOID
Definition: pg_type.h:698
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void compute_attributes_sql_style ( ParseState pstate,
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 605 of file functioncmds.c.

References DefElem::arg, compute_common_attribute(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, lfirst, DefElem::location, NIL, NULL, and parser_errposition().

Referenced by CreateFunction().

619 {
620  ListCell *option;
621  DefElem *as_item = NULL;
622  DefElem *language_item = NULL;
623  DefElem *transform_item = NULL;
624  DefElem *windowfunc_item = NULL;
625  DefElem *volatility_item = NULL;
626  DefElem *strict_item = NULL;
627  DefElem *security_item = NULL;
628  DefElem *leakproof_item = NULL;
629  List *set_items = NIL;
630  DefElem *cost_item = NULL;
631  DefElem *rows_item = NULL;
632  DefElem *parallel_item = NULL;
633 
634  foreach(option, options)
635  {
636  DefElem *defel = (DefElem *) lfirst(option);
637 
638  if (strcmp(defel->defname, "as") == 0)
639  {
640  if (as_item)
641  ereport(ERROR,
642  (errcode(ERRCODE_SYNTAX_ERROR),
643  errmsg("conflicting or redundant options"),
644  parser_errposition(pstate, defel->location)));
645  as_item = defel;
646  }
647  else if (strcmp(defel->defname, "language") == 0)
648  {
649  if (language_item)
650  ereport(ERROR,
651  (errcode(ERRCODE_SYNTAX_ERROR),
652  errmsg("conflicting or redundant options"),
653  parser_errposition(pstate, defel->location)));
654  language_item = defel;
655  }
656  else if (strcmp(defel->defname, "transform") == 0)
657  {
658  if (transform_item)
659  ereport(ERROR,
660  (errcode(ERRCODE_SYNTAX_ERROR),
661  errmsg("conflicting or redundant options"),
662  parser_errposition(pstate, defel->location)));
663  transform_item = defel;
664  }
665  else if (strcmp(defel->defname, "window") == 0)
666  {
667  if (windowfunc_item)
668  ereport(ERROR,
669  (errcode(ERRCODE_SYNTAX_ERROR),
670  errmsg("conflicting or redundant options"),
671  parser_errposition(pstate, defel->location)));
672  windowfunc_item = defel;
673  }
674  else if (compute_common_attribute(pstate,
675  defel,
676  &volatility_item,
677  &strict_item,
678  &security_item,
679  &leakproof_item,
680  &set_items,
681  &cost_item,
682  &rows_item,
683  &parallel_item))
684  {
685  /* recognized common option */
686  continue;
687  }
688  else
689  elog(ERROR, "option \"%s\" not recognized",
690  defel->defname);
691  }
692 
693  /* process required items */
694  if (as_item)
695  *as = (List *) as_item->arg;
696  else
697  {
698  ereport(ERROR,
699  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
700  errmsg("no function body specified")));
701  *as = NIL; /* keep compiler quiet */
702  }
703 
704  if (language_item)
705  *language = strVal(language_item->arg);
706  else
707  {
708  ereport(ERROR,
709  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
710  errmsg("no language specified")));
711  *language = NULL; /* keep compiler quiet */
712  }
713 
714  /* process optional items */
715  if (transform_item)
716  *transform = transform_item->arg;
717  if (windowfunc_item)
718  *windowfunc_p = intVal(windowfunc_item->arg);
719  if (volatility_item)
720  *volatility_p = interpret_func_volatility(volatility_item);
721  if (strict_item)
722  *strict_p = intVal(strict_item->arg);
723  if (security_item)
724  *security_definer = intVal(security_item->arg);
725  if (leakproof_item)
726  *leakproof_p = intVal(leakproof_item->arg);
727  if (set_items)
728  *proconfig = update_proconfig_value(NULL, set_items);
729  if (cost_item)
730  {
731  *procost = defGetNumeric(cost_item);
732  if (*procost <= 0)
733  ereport(ERROR,
734  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
735  errmsg("COST must be positive")));
736  }
737  if (rows_item)
738  {
739  *prorows = defGetNumeric(rows_item);
740  if (*prorows <= 0)
741  ereport(ERROR,
742  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
743  errmsg("ROWS must be positive")));
744  }
745  if (parallel_item)
746  *parallel_p = interpret_func_parallel(parallel_item);
747 }
#define NIL
Definition: pg_list.h:69
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:532
Node * arg
Definition: parsenodes.h:720
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:575
#define NULL
Definition: c.h:229
#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
static bool compute_common_attribute(ParseState *pstate, 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:453
Definition: pg_list.h:45
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:550
static void compute_attributes_with_style ( ParseState pstate,
List parameters,
bool isStrict_p,
char *  volatility_p 
)
static

Definition at line 765 of file functioncmds.c.

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

Referenced by CreateFunction().

766 {
767  ListCell *pl;
768 
769  foreach(pl, parameters)
770  {
771  DefElem *param = (DefElem *) lfirst(pl);
772 
773  if (pg_strcasecmp(param->defname, "isstrict") == 0)
774  *isStrict_p = defGetBoolean(param);
775  else if (pg_strcasecmp(param->defname, "iscachable") == 0)
776  {
777  /* obsolete spelling of isImmutable */
778  if (defGetBoolean(param))
779  *volatility_p = PROVOLATILE_IMMUTABLE;
780  }
781  else
783  (errcode(ERRCODE_SYNTAX_ERROR),
784  errmsg("unrecognized function attribute \"%s\" ignored",
785  param->defname),
786  parser_errposition(pstate, param->location)));
787  }
788 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5486
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
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
static bool compute_common_attribute ( ParseState pstate,
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 453 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().

463 {
464  if (strcmp(defel->defname, "volatility") == 0)
465  {
466  if (*volatility_item)
467  goto duplicate_error;
468 
469  *volatility_item = defel;
470  }
471  else if (strcmp(defel->defname, "strict") == 0)
472  {
473  if (*strict_item)
474  goto duplicate_error;
475 
476  *strict_item = defel;
477  }
478  else if (strcmp(defel->defname, "security") == 0)
479  {
480  if (*security_item)
481  goto duplicate_error;
482 
483  *security_item = defel;
484  }
485  else if (strcmp(defel->defname, "leakproof") == 0)
486  {
487  if (*leakproof_item)
488  goto duplicate_error;
489 
490  *leakproof_item = defel;
491  }
492  else if (strcmp(defel->defname, "set") == 0)
493  {
494  *set_items = lappend(*set_items, defel->arg);
495  }
496  else if (strcmp(defel->defname, "cost") == 0)
497  {
498  if (*cost_item)
499  goto duplicate_error;
500 
501  *cost_item = defel;
502  }
503  else if (strcmp(defel->defname, "rows") == 0)
504  {
505  if (*rows_item)
506  goto duplicate_error;
507 
508  *rows_item = defel;
509  }
510  else if (strcmp(defel->defname, "parallel") == 0)
511  {
512  if (*parallel_item)
513  goto duplicate_error;
514 
515  *parallel_item = defel;
516  }
517  else
518  return false;
519 
520  /* Recognized an option */
521  return true;
522 
523 duplicate_error:
524  ereport(ERROR,
525  (errcode(ERRCODE_SYNTAX_ERROR),
526  errmsg("conflicting or redundant options"),
527  parser_errposition(pstate, defel->location)));
528  return false; /* keep compiler quiet */
529 }
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
static void compute_return_type ( TypeName returnType,
Oid  languageOid,
Oid prorettype_p,
bool returnsSet_p 
)
static

Definition at line 83 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, NULL, ObjectAddress::objectId, OidIsValid, pg_namespace_aclcheck(), pg_type_aclcheck(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, SQLlanguageId, TypeNameToString(), TypeShellMake(), typeTypeId(), and TypeName::typmods.

Referenced by CreateFunction().

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

Definition at line 1398 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, NULL, 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().

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

Definition at line 861 of file functioncmds.c.

References ACL_CREATE, ACL_KIND_LANGUAGE, ACL_KIND_NAMESPACE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, 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(), LANGNAME, lappend_oid(), lfirst_node, lfirst_oid, list_length(), NameStr, NIL, NULL, 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().

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

Definition at line 1797 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, NULL, 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().

1798 {
1799  Oid typeid;
1800  char typtype;
1801  Oid langid;
1802  Oid fromsqlfuncid;
1803  Oid tosqlfuncid;
1804  AclResult aclresult;
1805  Form_pg_proc procstruct;
1807  bool nulls[Natts_pg_transform];
1808  bool replaces[Natts_pg_transform];
1809  Oid transformid;
1810  HeapTuple tuple;
1811  HeapTuple newtuple;
1812  Relation relation;
1813  ObjectAddress myself,
1814  referenced;
1815  bool is_replace;
1816 
1817  /*
1818  * Get the type
1819  */
1820  typeid = typenameTypeId(NULL, stmt->type_name);
1821  typtype = get_typtype(typeid);
1822 
1823  if (typtype == TYPTYPE_PSEUDO)
1824  ereport(ERROR,
1825  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1826  errmsg("data type %s is a pseudo-type",
1827  TypeNameToString(stmt->type_name))));
1828 
1829  if (typtype == TYPTYPE_DOMAIN)
1830  ereport(ERROR,
1831  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1832  errmsg("data type %s is a domain",
1833  TypeNameToString(stmt->type_name))));
1834 
1835  if (!pg_type_ownercheck(typeid, GetUserId()))
1837 
1838  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1839  if (aclresult != ACLCHECK_OK)
1840  aclcheck_error_type(aclresult, typeid);
1841 
1842  /*
1843  * Get the language
1844  */
1845  langid = get_language_oid(stmt->lang, false);
1846 
1847  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1848  if (aclresult != ACLCHECK_OK)
1849  aclcheck_error(aclresult, ACL_KIND_LANGUAGE, stmt->lang);
1850 
1851  /*
1852  * Get the functions
1853  */
1854  if (stmt->fromsql)
1855  {
1856  fromsqlfuncid = LookupFuncWithArgs(stmt->fromsql, false);
1857 
1858  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1860 
1861  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1862  if (aclresult != ACLCHECK_OK)
1864 
1865  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1866  if (!HeapTupleIsValid(tuple))
1867  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1868  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1869  if (procstruct->prorettype != INTERNALOID)
1870  ereport(ERROR,
1871  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1872  errmsg("return data type of FROM SQL function must be %s",
1873  "internal")));
1874  check_transform_function(procstruct);
1875  ReleaseSysCache(tuple);
1876  }
1877  else
1878  fromsqlfuncid = InvalidOid;
1879 
1880  if (stmt->tosql)
1881  {
1882  tosqlfuncid = LookupFuncWithArgs(stmt->tosql, false);
1883 
1884  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1886 
1887  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1888  if (aclresult != ACLCHECK_OK)
1890 
1891  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1892  if (!HeapTupleIsValid(tuple))
1893  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1894  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1895  if (procstruct->prorettype != typeid)
1896  ereport(ERROR,
1897  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1898  errmsg("return data type of TO SQL function must be the transform data type")));
1899  check_transform_function(procstruct);
1900  ReleaseSysCache(tuple);
1901  }
1902  else
1903  tosqlfuncid = InvalidOid;
1904 
1905  /*
1906  * Ready to go
1907  */
1908  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1909  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1910  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1911  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1912 
1913  MemSet(nulls, false, sizeof(nulls));
1914 
1916 
1917  tuple = SearchSysCache2(TRFTYPELANG,
1918  ObjectIdGetDatum(typeid),
1919  ObjectIdGetDatum(langid));
1920  if (HeapTupleIsValid(tuple))
1921  {
1922  if (!stmt->replace)
1923  ereport(ERROR,
1925  errmsg("transform for type %s language \"%s\" already exists",
1926  format_type_be(typeid),
1927  stmt->lang)));
1928 
1929  MemSet(replaces, false, sizeof(replaces));
1930  replaces[Anum_pg_transform_trffromsql - 1] = true;
1931  replaces[Anum_pg_transform_trftosql - 1] = true;
1932 
1933  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1934  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1935 
1936  transformid = HeapTupleGetOid(tuple);
1937  ReleaseSysCache(tuple);
1938  is_replace = true;
1939  }
1940  else
1941  {
1942  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1943  transformid = CatalogTupleInsert(relation, newtuple);
1944  is_replace = false;
1945  }
1946 
1947  if (is_replace)
1948  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1949 
1950  /* make dependency entries */
1951  myself.classId = TransformRelationId;
1952  myself.objectId = transformid;
1953  myself.objectSubId = 0;
1954 
1955  /* dependency on language */
1956  referenced.classId = LanguageRelationId;
1957  referenced.objectId = langid;
1958  referenced.objectSubId = 0;
1959  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1960 
1961  /* dependency on type */
1962  referenced.classId = TypeRelationId;
1963  referenced.objectId = typeid;
1964  referenced.objectSubId = 0;
1965  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1966 
1967  /* dependencies on functions */
1968  if (OidIsValid(fromsqlfuncid))
1969  {
1970  referenced.classId = ProcedureRelationId;
1971  referenced.objectId = fromsqlfuncid;
1972  referenced.objectSubId = 0;
1973  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1974  }
1975  if (OidIsValid(tosqlfuncid))
1976  {
1977  referenced.classId = ProcedureRelationId;
1978  referenced.objectId = tosqlfuncid;
1979  referenced.objectSubId = 0;
1980  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1981  }
1982 
1983  /* dependency on extension */
1984  recordDependencyOnCurrentExtension(&myself, is_replace);
1985 
1986  /* Post creation hook for new transform */
1988 
1989  heap_freetuple(newtuple);
1990 
1991  heap_close(relation, RowExclusiveLock);
1992 
1993  return myself;
1994 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
ObjectWithArgs * tosql
Definition: parsenodes.h:3260
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define TransformRelationId
Definition: pg_transform.h:25
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:283
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:2379
#define MemSet(start, val, len)
Definition: c.h:857
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:692
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4572
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:538
#define Anum_pg_transform_trftosql
Definition: pg_transform.h:45
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4458
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#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:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
Oid LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
Definition: parse_func.c:1990
char * NameListToString(List *names)
Definition: namespace.c:3063
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3259
#define Anum_pg_transform_trffromsql
Definition: pg_transform.h:44
#define INTERNALOID
Definition: pg_type.h:698
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
#define Anum_pg_transform_trftype
Definition: pg_transform.h:42
TypeName * type_name
Definition: parsenodes.h:3257
static Datum values[MAXATTR]
Definition: bootstrap.c:163
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:4446
#define LanguageRelationId
Definition: pg_language.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4534
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:791
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4624
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:158
void DropCastById ( Oid  castOid)

Definition at line 1736 of file functioncmds.c.

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

Referenced by doDeletion().

1737 {
1738  Relation relation;
1739  ScanKeyData scankey;
1740  SysScanDesc scan;
1741  HeapTuple tuple;
1742 
1744 
1745  ScanKeyInit(&scankey,
1747  BTEqualStrategyNumber, F_OIDEQ,
1748  ObjectIdGetDatum(castOid));
1749  scan = systable_beginscan(relation, CastOidIndexId, true,
1750  NULL, 1, &scankey);
1751 
1752  tuple = systable_getnext(scan);
1753  if (!HeapTupleIsValid(tuple))
1754  elog(ERROR, "could not find tuple for cast %u", castOid);
1755  CatalogTupleDelete(relation, &tuple->t_self);
1756 
1757  systable_endscan(scan);
1758  heap_close(relation, RowExclusiveLock);
1759 }
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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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
void DropTransformById ( Oid  transformOid)

Definition at line 2022 of file functioncmds.c.

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

Referenced by doDeletion().

2023 {
2024  Relation relation;
2025  ScanKeyData scankey;
2026  SysScanDesc scan;
2027  HeapTuple tuple;
2028 
2030 
2031  ScanKeyInit(&scankey,
2033  BTEqualStrategyNumber, F_OIDEQ,
2034  ObjectIdGetDatum(transformOid));
2035  scan = systable_beginscan(relation, TransformOidIndexId, true,
2036  NULL, 1, &scankey);
2037 
2038  tuple = systable_getnext(scan);
2039  if (!HeapTupleIsValid(tuple))
2040  elog(ERROR, "could not find tuple for transform %u", transformOid);
2041  CatalogTupleDelete(relation, &tuple->t_self);
2042 
2043  systable_endscan(scan);
2044  heap_close(relation, RowExclusiveLock);
2045 }
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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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
void ExecuteDoStmt ( DoStmt stmt)

Definition at line 2076 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, NULL, OidFunctionCall1, OidIsValid, pg_language_aclcheck(), PLTemplateExists(), PointerGetDatum, ReleaseSysCache(), SearchSysCache1, InlineCodeBlock::source_text, strVal, and superuser().

Referenced by standard_ProcessUtility().

2077 {
2079  ListCell *arg;
2080  DefElem *as_item = NULL;
2081  DefElem *language_item = NULL;
2082  char *language;
2083  Oid laninline;
2084  HeapTuple languageTuple;
2085  Form_pg_language languageStruct;
2086 
2087  /* Process options we got from gram.y */
2088  foreach(arg, stmt->args)
2089  {
2090  DefElem *defel = (DefElem *) lfirst(arg);
2091 
2092  if (strcmp(defel->defname, "as") == 0)
2093  {
2094  if (as_item)
2095  ereport(ERROR,
2096  (errcode(ERRCODE_SYNTAX_ERROR),
2097  errmsg("conflicting or redundant options")));
2098  as_item = defel;
2099  }
2100  else if (strcmp(defel->defname, "language") == 0)
2101  {
2102  if (language_item)
2103  ereport(ERROR,
2104  (errcode(ERRCODE_SYNTAX_ERROR),
2105  errmsg("conflicting or redundant options")));
2106  language_item = defel;
2107  }
2108  else
2109  elog(ERROR, "option \"%s\" not recognized",
2110  defel->defname);
2111  }
2112 
2113  if (as_item)
2114  codeblock->source_text = strVal(as_item->arg);
2115  else
2116  ereport(ERROR,
2117  (errcode(ERRCODE_SYNTAX_ERROR),
2118  errmsg("no inline code specified")));
2119 
2120  /* if LANGUAGE option wasn't specified, use the default */
2121  if (language_item)
2122  language = strVal(language_item->arg);
2123  else
2124  language = "plpgsql";
2125 
2126  /* Look up the language and validate permissions */
2127  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2128  if (!HeapTupleIsValid(languageTuple))
2129  ereport(ERROR,
2130  (errcode(ERRCODE_UNDEFINED_OBJECT),
2131  errmsg("language \"%s\" does not exist", language),
2132  (PLTemplateExists(language) ?
2133  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
2134 
2135  codeblock->langOid = HeapTupleGetOid(languageTuple);
2136  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2137  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2138 
2139  if (languageStruct->lanpltrusted)
2140  {
2141  /* if trusted language, need USAGE privilege */
2142  AclResult aclresult;
2143 
2144  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2145  ACL_USAGE);
2146  if (aclresult != ACLCHECK_OK)
2147  aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
2148  NameStr(languageStruct->lanname));
2149  }
2150  else
2151  {
2152  /* if untrusted language, must be superuser */
2153  if (!superuser())
2155  NameStr(languageStruct->lanname));
2156  }
2157 
2158  /* get the handler function's OID */
2159  laninline = languageStruct->laninline;
2160  if (!OidIsValid(laninline))
2161  ereport(ERROR,
2162  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2163  errmsg("language \"%s\" does not support inline code execution",
2164  NameStr(languageStruct->lanname))));
2165 
2166  ReleaseSysCache(languageTuple);
2167 
2168  /* execute the inline handler */
2169  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2170 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:283
#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:538
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4458
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:622
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
AclResult
Definition: acl.h:170
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:519
#define makeNode(_type_)
Definition: nodes.h:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: parsenodes.h:2768
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:499
void * arg
char * source_text
Definition: parsenodes.h:2774
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Oid get_cast_oid ( Oid  sourcetypeid,
Oid  targettypeid,
bool  missing_ok 
)

Definition at line 1719 of file functioncmds.c.

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

Referenced by get_object_address().

1720 {
1721  Oid oid;
1722 
1724  ObjectIdGetDatum(sourcetypeid),
1725  ObjectIdGetDatum(targettypeid));
1726  if (!OidIsValid(oid) && !missing_ok)
1727  ereport(ERROR,
1728  (errcode(ERRCODE_UNDEFINED_OBJECT),
1729  errmsg("cast from type %s to type %s does not exist",
1730  format_type_be(sourcetypeid),
1731  format_type_be(targettypeid))));
1732  return oid;
1733 }
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:538
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:185
#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
Oid get_transform_oid ( Oid  type_id,
Oid  lang_id,
bool  missing_ok 
)

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

2005 {
2006  Oid oid;
2007 
2009  ObjectIdGetDatum(type_id),
2010  ObjectIdGetDatum(lang_id));
2011  if (!OidIsValid(oid) && !missing_ok)
2012  ereport(ERROR,
2013  (errcode(ERRCODE_UNDEFINED_OBJECT),
2014  errmsg("transform for type %s language \"%s\" does not exist",
2015  format_type_be(type_id),
2016  get_language_name(lang_id, false))));
2017  return oid;
2018 }
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:538
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:185
#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
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 801 of file functioncmds.c.

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

Referenced by CreateFunction().

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

Definition at line 550 of file functioncmds.c.

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

Referenced by AlterFunction().

551 {
552  char *str = strVal(defel->arg);
553 
554  if (strcmp(str, "safe") == 0)
555  return PROPARALLEL_SAFE;
556  else if (strcmp(str, "unsafe") == 0)
557  return PROPARALLEL_UNSAFE;
558  else if (strcmp(str, "restricted") == 0)
559  return PROPARALLEL_RESTRICTED;
560  else
561  {
562  ereport(ERROR,
563  (errcode(ERRCODE_SYNTAX_ERROR),
564  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
565  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
566  }
567 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PROPARALLEL_RESTRICTED
Definition: pg_proc.h:5496
#define ERROR
Definition: elog.h:43
#define PROPARALLEL_SAFE
Definition: pg_proc.h:5495
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5497
Node * arg
Definition: parsenodes.h:720
int errmsg(const char *fmt,...)
Definition: elog.c:797
static char interpret_func_volatility ( DefElem defel)
static

Definition at line 532 of file functioncmds.c.

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

Referenced by AlterFunction().

533 {
534  char *str = strVal(defel->arg);
535 
536  if (strcmp(str, "immutable") == 0)
537  return PROVOLATILE_IMMUTABLE;
538  else if (strcmp(str, "stable") == 0)
539  return PROVOLATILE_STABLE;
540  else if (strcmp(str, "volatile") == 0)
541  return PROVOLATILE_VOLATILE;
542  else
543  {
544  elog(ERROR, "invalid volatility \"%s\"", str);
545  return 0; /* keep compiler quiet */
546  }
547 }
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5486
#define strVal(v)
Definition: value.h:54
#define ERROR
Definition: elog.h:43
#define PROVOLATILE_STABLE
Definition: pg_proc.h:5487
Node * arg
Definition: parsenodes.h:720
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5488
#define elog
Definition: elog.h:219
void interpret_function_parameter_list ( ParseState pstate,
List parameters,
Oid  languageOid,
bool  is_aggregate,
oidvector **  parameterTypes,
ArrayType **  allParameterTypes,
ArrayType **  parameterModes,
ArrayType **  parameterNames,
List **  parameterDefaults,
Oid variadicArgType,
Oid requiredResultType 
)

Definition at line 179 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_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, NULL, 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().

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

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

2057 {
2058  /* check for duplicate name (more friendly than unique-index failure) */
2060  CStringGetDatum(proname),
2061  PointerGetDatum(proargtypes),
2062  ObjectIdGetDatum(nspOid)))
2063  ereport(ERROR,
2064  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2065  errmsg("function %s already exists in schema \"%s\"",
2066  funcname_signature_string(proname, pronargs,
2067  NIL, proargtypes->values),
2068  get_namespace_name(nspOid))));
2069 }
#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:178
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:486
#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:1871
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RemoveFunctionById ( Oid  funcOid)

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

1119 {
1120  Relation relation;
1121  HeapTuple tup;
1122  bool isagg;
1123 
1124  /*
1125  * Delete the pg_proc tuple.
1126  */
1128 
1129  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1130  if (!HeapTupleIsValid(tup)) /* should not happen */
1131  elog(ERROR, "cache lookup failed for function %u", funcOid);
1132 
1133  isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
1134 
1135  CatalogTupleDelete(relation, &tup->t_self);
1136 
1137  ReleaseSysCache(tup);
1138 
1139  heap_close(relation, RowExclusiveLock);
1140 
1141  /*
1142  * If there's a pg_aggregate tuple, delete that too.
1143  */
1144  if (isagg)
1145  {
1147 
1148  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1149  if (!HeapTupleIsValid(tup)) /* should not happen */
1150  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1151 
1152  CatalogTupleDelete(relation, &tup->t_self);
1153 
1154  ReleaseSysCache(tup);
1155 
1156  heap_close(relation, RowExclusiveLock);
1157  }
1158 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#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
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void SetFunctionArgType ( Oid  funcOid,
int  argIndex,
Oid  newArgType 
)

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

1357 {
1358  Relation pg_proc_rel;
1359  HeapTuple tup;
1360  Form_pg_proc procForm;
1361  ObjectAddress func_address;
1362  ObjectAddress type_address;
1363 
1365 
1366  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1367  if (!HeapTupleIsValid(tup)) /* should not happen */
1368  elog(ERROR, "cache lookup failed for function %u", funcOid);
1369  procForm = (Form_pg_proc) GETSTRUCT(tup);
1370 
1371  if (argIndex < 0 || argIndex >= procForm->pronargs ||
1372  procForm->proargtypes.values[argIndex] != OPAQUEOID)
1373  elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1374 
1375  /* okay to overwrite copied tuple */
1376  procForm->proargtypes.values[argIndex] = newArgType;
1377 
1378  /* update the catalog and its indexes */
1379  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1380 
1381  heap_close(pg_proc_rel, RowExclusiveLock);
1382 
1383  /*
1384  * Also update the dependency to the new type. Opaque is a pinned type, so
1385  * there is no old dependency record for it that we would need to remove.
1386  */
1387  ObjectAddressSet(type_address, TypeRelationId, newArgType);
1388  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1389  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1390 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:1284
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:165
#define elog
Definition: elog.h:219
void SetFunctionReturnType ( Oid  funcOid,
Oid  newRetType 
)

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

1315 {
1316  Relation pg_proc_rel;
1317  HeapTuple tup;
1318  Form_pg_proc procForm;
1319  ObjectAddress func_address;
1320  ObjectAddress type_address;
1321 
1323 
1324  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1325  if (!HeapTupleIsValid(tup)) /* should not happen */
1326  elog(ERROR, "cache lookup failed for function %u", funcOid);
1327  procForm = (Form_pg_proc) GETSTRUCT(tup);
1328 
1329  if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1330  elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1331 
1332  /* okay to overwrite copied tuple */
1333  procForm->prorettype = newRetType;
1334 
1335  /* update the catalog and its indexes */
1336  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1337 
1338  heap_close(pg_proc_rel, RowExclusiveLock);
1339 
1340  /*
1341  * Also update the dependency to the new type. Opaque is a pinned type, so
1342  * there is no old dependency record for it that we would need to remove.
1343  */
1344  ObjectAddressSet(type_address, TypeRelationId, newRetType);
1345  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1346  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1347 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:1284
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:165
#define elog
Definition: elog.h:219
static ArrayType* update_proconfig_value ( ArrayType a,
List set_items 
)
static

Definition at line 575 of file functioncmds.c.

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

Referenced by AlterFunction().

576 {
577  ListCell *l;
578 
579  foreach(l, set_items)
580  {
582 
583  if (sstmt->kind == VAR_RESET_ALL)
584  a = NULL;
585  else
586  {
587  char *valuestr = ExtractSetVariableArgs(sstmt);
588 
589  if (valuestr)
590  a = GUCArrayAdd(a, sstmt->name, valuestr);
591  else /* RESET */
592  a = GUCArrayDelete(a, sstmt->name);
593  }
594  }
595 
596  return a;
597 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:9470
VariableSetKind kind
Definition: parsenodes.h:1957
#define lfirst_node(type, lc)
Definition: pg_list.h:109
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:9550
#define NULL
Definition: c.h:229
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:7409