PostgreSQL Source Code  git master
proclang.h File Reference
Include dependency graph for proclang.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress CreateProceduralLanguage (CreatePLangStmt *stmt)
 
void DropProceduralLanguageById (Oid langOid)
 
bool PLTemplateExists (const char *languageName)
 
Oid get_language_oid (const char *langname, bool missing_ok)
 

Function Documentation

◆ CreateProceduralLanguage()

ObjectAddress CreateProceduralLanguage ( CreatePLangStmt stmt)

Definition at line 63 of file proclang.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, buildoidvector(), create_proc_lang(), ereport, errcode(), errhint(), errmsg(), ERROR, find_language_template(), get_database_name(), get_func_rettype(), GetUserId(), InvalidOid, LookupFuncName(), MyDatabaseId, NameListToString(), NIL, NOTICE, OBJECT_DATABASE, ObjectAddress::objectId, OidIsValid, pg_database_ownercheck(), CreatePLangStmt::plhandler, CreatePLangStmt::plinline, CreatePLangStmt::plname, CreatePLangStmt::pltrusted, CreatePLangStmt::plvalidator, PointerGetDatum, ProcedureCreate(), CreatePLangStmt::replace, SetFunctionReturnType(), superuser(), SystemFuncName(), PLTemplate::tmpldbacreate, PLTemplate::tmplhandler, PLTemplate::tmplinline, PLTemplate::tmpllibrary, PLTemplate::tmpltrusted, PLTemplate::tmplvalidator, and WARNING.

Referenced by ProcessUtilitySlow().

64 {
65  PLTemplate *pltemplate;
66  ObjectAddress tmpAddr;
67  Oid handlerOid,
68  inlineOid,
69  valOid;
70  Oid funcrettype;
71  Oid funcargtypes[1];
72 
73  /*
74  * If we have template information for the language, ignore the supplied
75  * parameters (if any) and use the template information.
76  */
77  if ((pltemplate = find_language_template(stmt->plname)) != NULL)
78  {
79  List *funcname;
80 
81  /*
82  * Give a notice if we are ignoring supplied parameters.
83  */
84  if (stmt->plhandler)
86  (errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));
87 
88  /*
89  * Check permission
90  */
91  if (!superuser())
92  {
93  if (!pltemplate->tmpldbacreate)
94  ereport(ERROR,
95  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
96  errmsg("must be superuser to create procedural language \"%s\"",
97  stmt->plname)));
101  }
102 
103  /*
104  * Find or create the handler function, which we force to be in the
105  * pg_catalog schema. If already present, it must have the correct
106  * return type.
107  */
108  funcname = SystemFuncName(pltemplate->tmplhandler);
109  handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
110  if (OidIsValid(handlerOid))
111  {
112  funcrettype = get_func_rettype(handlerOid);
113  if (funcrettype != LANGUAGE_HANDLEROID)
114  ereport(ERROR,
115  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
116  errmsg("function %s must return type %s",
117  NameListToString(funcname), "language_handler")));
118  }
119  else
120  {
121  tmpAddr = ProcedureCreate(pltemplate->tmplhandler,
122  PG_CATALOG_NAMESPACE,
123  false, /* replace */
124  false, /* returnsSet */
125  LANGUAGE_HANDLEROID,
126  BOOTSTRAP_SUPERUSERID,
127  ClanguageId,
128  F_FMGR_C_VALIDATOR,
129  pltemplate->tmplhandler,
130  pltemplate->tmpllibrary,
131  PROKIND_FUNCTION,
132  false, /* security_definer */
133  false, /* isLeakProof */
134  false, /* isStrict */
135  PROVOLATILE_VOLATILE,
136  PROPARALLEL_UNSAFE,
137  buildoidvector(funcargtypes, 0),
138  PointerGetDatum(NULL),
139  PointerGetDatum(NULL),
140  PointerGetDatum(NULL),
141  NIL,
142  PointerGetDatum(NULL),
143  PointerGetDatum(NULL),
144  1,
145  0);
146  handlerOid = tmpAddr.objectId;
147  }
148 
149  /*
150  * Likewise for the anonymous block handler, if required; but we don't
151  * care about its return type.
152  */
153  if (pltemplate->tmplinline)
154  {
155  funcname = SystemFuncName(pltemplate->tmplinline);
156  funcargtypes[0] = INTERNALOID;
157  inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
158  if (!OidIsValid(inlineOid))
159  {
160  tmpAddr = ProcedureCreate(pltemplate->tmplinline,
161  PG_CATALOG_NAMESPACE,
162  false, /* replace */
163  false, /* returnsSet */
164  VOIDOID,
165  BOOTSTRAP_SUPERUSERID,
166  ClanguageId,
167  F_FMGR_C_VALIDATOR,
168  pltemplate->tmplinline,
169  pltemplate->tmpllibrary,
170  PROKIND_FUNCTION,
171  false, /* security_definer */
172  false, /* isLeakProof */
173  true, /* isStrict */
174  PROVOLATILE_VOLATILE,
175  PROPARALLEL_UNSAFE,
176  buildoidvector(funcargtypes, 1),
177  PointerGetDatum(NULL),
178  PointerGetDatum(NULL),
179  PointerGetDatum(NULL),
180  NIL,
181  PointerGetDatum(NULL),
182  PointerGetDatum(NULL),
183  1,
184  0);
185  inlineOid = tmpAddr.objectId;
186  }
187  }
188  else
189  inlineOid = InvalidOid;
190 
191  /*
192  * Likewise for the validator, if required; but we don't care about
193  * its return type.
194  */
195  if (pltemplate->tmplvalidator)
196  {
197  funcname = SystemFuncName(pltemplate->tmplvalidator);
198  funcargtypes[0] = OIDOID;
199  valOid = LookupFuncName(funcname, 1, funcargtypes, true);
200  if (!OidIsValid(valOid))
201  {
202  tmpAddr = ProcedureCreate(pltemplate->tmplvalidator,
203  PG_CATALOG_NAMESPACE,
204  false, /* replace */
205  false, /* returnsSet */
206  VOIDOID,
207  BOOTSTRAP_SUPERUSERID,
208  ClanguageId,
209  F_FMGR_C_VALIDATOR,
210  pltemplate->tmplvalidator,
211  pltemplate->tmpllibrary,
212  PROKIND_FUNCTION,
213  false, /* security_definer */
214  false, /* isLeakProof */
215  true, /* isStrict */
216  PROVOLATILE_VOLATILE,
217  PROPARALLEL_UNSAFE,
218  buildoidvector(funcargtypes, 1),
219  PointerGetDatum(NULL),
220  PointerGetDatum(NULL),
221  PointerGetDatum(NULL),
222  NIL,
223  PointerGetDatum(NULL),
224  PointerGetDatum(NULL),
225  1,
226  0);
227  valOid = tmpAddr.objectId;
228  }
229  }
230  else
231  valOid = InvalidOid;
232 
233  /* ok, create it */
234  return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
235  handlerOid, inlineOid,
236  valOid, pltemplate->tmpltrusted);
237  }
238  else
239  {
240  /*
241  * No template, so use the provided information. If there's no
242  * handler clause, the user is trying to rely on a template that we
243  * don't have, so complain accordingly.
244  */
245  if (!stmt->plhandler)
246  ereport(ERROR,
247  (errcode(ERRCODE_UNDEFINED_OBJECT),
248  errmsg("unsupported language \"%s\"",
249  stmt->plname),
250  errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
251 
252  /*
253  * Check permission
254  */
255  if (!superuser())
256  ereport(ERROR,
257  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
258  errmsg("must be superuser to create custom procedural language")));
259 
260  /*
261  * Lookup the PL handler function and check that it is of the expected
262  * return type
263  */
264  handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
265  funcrettype = get_func_rettype(handlerOid);
266  if (funcrettype != LANGUAGE_HANDLEROID)
267  {
268  /*
269  * We allow OPAQUE just so we can load old dump files. When we
270  * see a handler function declared OPAQUE, change it to
271  * LANGUAGE_HANDLER. (This is probably obsolete and removable?)
272  */
273  if (funcrettype == OPAQUEOID)
274  {
276  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
277  errmsg("changing return type of function %s from %s to %s",
279  "opaque", "language_handler")));
280  SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
281  }
282  else
283  ereport(ERROR,
284  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
285  errmsg("function %s must return type %s",
286  NameListToString(stmt->plhandler), "language_handler")));
287  }
288 
289  /* validate the inline function */
290  if (stmt->plinline)
291  {
292  funcargtypes[0] = INTERNALOID;
293  inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
294  /* return value is ignored, so we don't check the type */
295  }
296  else
297  inlineOid = InvalidOid;
298 
299  /* validate the validator function */
300  if (stmt->plvalidator)
301  {
302  funcargtypes[0] = OIDOID;
303  valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
304  /* return value is ignored, so we don't check the type */
305  }
306  else
307  valOid = InvalidOid;
308 
309  /* ok, create it */
310  return create_proc_lang(stmt->plname, stmt->replace, GetUserId(),
311  handlerOid, inlineOid,
312  valOid, stmt->pltrusted);
313  }
314 }
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, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, float4 procost, float4 prorows)
Definition: pg_proc.c:66
#define NIL
Definition: pg_list.h:69
List * SystemFuncName(char *name)
int errhint(const char *fmt,...)
Definition: elog.c:987
char * tmpllibrary
Definition: proclang.c:50
Oid GetUserId(void)
Definition: miscinit.c:379
#define PointerGetDatum(X)
Definition: postgres.h:539
bool tmpltrusted
Definition: proclang.c:45
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
static ObjectAddress create_proc_lang(const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted)
Definition: proclang.c:320
#define OidIsValid(objectId)
Definition: c.h:605
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1444
char * tmplinline
Definition: proclang.c:48
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
#define ERROR
Definition: elog.h:43
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
#define ereport(elevel, rest)
Definition: elog.h:122
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5166
List * plvalidator
Definition: parsenodes.h:2425
bool tmpldbacreate
Definition: proclang.c:46
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3082
Oid MyDatabaseId
Definition: globals.c:86
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1974
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * tmplhandler
Definition: proclang.c:47
static PLTemplate * find_language_template(const char *languageName)
Definition: proclang.c:447
Definition: pg_list.h:45
char * tmplvalidator
Definition: proclang.c:49

◆ DropProceduralLanguageById()

void DropProceduralLanguageById ( Oid  langOid)

Definition at line 524 of file proclang.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, LANGOID, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

525 {
526  Relation rel;
527  HeapTuple langTup;
528 
529  rel = heap_open(LanguageRelationId, RowExclusiveLock);
530 
531  langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(langOid));
532  if (!HeapTupleIsValid(langTup)) /* should not happen */
533  elog(ERROR, "cache lookup failed for language %u", langOid);
534 
535  CatalogTupleDelete(rel, &langTup->t_self);
536 
537  ReleaseSysCache(langTup);
538 
540 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog
Definition: elog.h:219

◆ get_language_oid()

Oid get_language_oid ( const char *  langname,
bool  missing_ok 
)

Definition at line 549 of file proclang.c.

References CStringGetDatum, ereport, errcode(), errmsg(), ERROR, GetSysCacheOid1, LANGNAME, and OidIsValid.

Referenced by convert_language_name(), CreateTransform(), get_object_address(), get_object_address_unqualified(), and objectNamesToOids().

550 {
551  Oid oid;
552 
553  oid = GetSysCacheOid1(LANGNAME, CStringGetDatum(langname));
554  if (!OidIsValid(oid) && !missing_ok)
555  ereport(ERROR,
556  (errcode(ERRCODE_UNDEFINED_OBJECT),
557  errmsg("language \"%s\" does not exist", langname)));
558  return oid;
559 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:191
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:561
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ PLTemplateExists()

bool PLTemplateExists ( const char *  languageName)

Definition at line 515 of file proclang.c.

References find_language_template().

Referenced by CreateFunction(), and ExecuteDoStmt().

516 {
517  return (find_language_template(languageName) != NULL);
518 }
static PLTemplate * find_language_template(const char *languageName)
Definition: proclang.c:447